ngx-valdemort
Version:
Simple, consistent validation error messages for your Angular forms
465 lines (456 loc) • 22.5 kB
TypeScript
import * as i0 from '@angular/core';
import { TemplateRef, AfterContentInit, DoCheck, Signal } from '@angular/core';
import { AbstractControl, NgForm, FormGroupDirective } from '@angular/forms';
import { FieldTree, ValidationError, FieldState } from '@angular/forms/signals';
/**
* The context of the ValidationErrorDirective
*/
interface ValidationErrorContext {
/**
* The label
*/
$implicit: string | null;
/**
* The error
*/
error: any;
}
/**
* Directive allowing to define the template for an error of a given type (using the `valError` input), using an ng-template.
* It's used inside the body of the validation errors component, or inside the body of the default validation errors directive.
* See the documentation of these two for example usages.
*/
declare class ValidationErrorDirective {
readonly templateRef: TemplateRef<ValidationErrorContext>;
/**
* The type of the error that the content of the template must display.
*/
readonly type: i0.InputSignal<string>;
static ngTemplateContextGuard(_directive: ValidationErrorDirective, context: unknown): context is ValidationErrorContext;
static ɵfac: i0.ɵɵFactoryDeclaration<ValidationErrorDirective, never>;
static ɵdir: i0.ɵɵDirectiveDeclaration<ValidationErrorDirective, "ng-template[valError]", never, { "type": { "alias": "valError"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
}
/**
* The context of the ValidationFallbackDirective
*/
interface ValidationFallbackContext {
/**
* The label
*/
$implicit: string | null;
/**
* The error
*/
error: any;
/**
* The type of the error
*/
type: string;
}
/**
* Directive allowing to define a fallback template for an error of a type that is not handled by any validation error directive.
* It's used inside the body of the validation errors component, or inside the body of the default validation errors directive.
* See the documentation of these two for example usages.
*
* This is useful to handle forgotten errors instead of displaying no error at all, or to handle all or several error types in the same way,
* for example by relying on the error key to choose an internationalized message.
*/
declare class ValidationFallbackDirective {
readonly templateRef: TemplateRef<ValidationFallbackContext>;
static ngTemplateContextGuard(_directive: ValidationFallbackDirective, context: unknown): context is ValidationFallbackContext;
static ɵfac: i0.ɵɵFactoryDeclaration<ValidationFallbackDirective, never>;
static ɵdir: i0.ɵɵDirectiveDeclaration<ValidationFallbackDirective, "ng-template[valFallback]", never, {}, {}, never, never, true, never>;
}
/**
* Directive allowing to register default templates for validation error messages. It's supposed to be used once,
* typically in the root component. By using templates to do that, error messages can
* - easily be i18ned
* - easily use pipes
* - easily use HTML
* - easily be ordered
*
* Example usage:
* ```
* <val-default-errors>
* <ng-template valError="required">This field is mandatory</ng-template>
* <ng-template valError="max" let-error="error">This field must be at most {{ error.max | number }}</ng-template>
* </val-default-errors>
* ```
*
* Example usage where a label is used to make the messages less generic:
* ```
* <val-default-errors>
* <ng-template valError="required" let-label>{{ label }} is mandatory</ng-template>
* <ng-template valError="max" let-error="error" let-label>{{ label }} must be at most {{ error.max | number }}</ng-template>
* </val-default-errors>
* ```
*
* A fallback template can also be provided. This fallback template is used for all the errors that exist on the form control
* but are not handled by any of the specific error templates:
* ```
* <val-default-errors>
* <ng-template valError="required" let-label>{{ label }} is mandatory</ng-template>
* <ng-template valError="max" let-error="error" let-label>{{ label }} must be at most {{ error.max | number }}</ng-template>
* <ng-template valFallback let-label let-type="type" let-error="error">{{ label }} has an unhandled error of type {{ type }}: {{ error | json }}</ng-template>
* </val-default-errors>
* ```
* Using the fallback can also be used to handle all the errors the same way, for example by using the error type as an i18n key
* to display the appropriate error message.
*
* This directive stores the default template references in a service, that is then injected in the validation errors components
* to be reused.
*/
declare class DefaultValidationErrorsDirective implements AfterContentInit {
private defaultValidationErrors;
/**
* The list of validation error directives (i.e. <ng-template valError="...">)
* contained inside the directive element.
*/
readonly errorDirectives: i0.Signal<readonly ValidationErrorDirective[]>;
/**
* The validation fallback directive (i.e. <ng-template valFallback>) contained inside the directive element.
*/
readonly fallbackDirective: i0.Signal<ValidationFallbackDirective | undefined>;
ngAfterContentInit(): void;
static ɵfac: i0.ɵɵFactoryDeclaration<DefaultValidationErrorsDirective, never>;
static ɵdir: i0.ɵɵDirectiveDeclaration<DefaultValidationErrorsDirective, "val-default-errors", never, {}, {}, ["errorDirectives", "fallbackDirective"], never, true, never>;
}
interface FallbackError {
type: string;
value: any;
}
interface ErrorsToDisplay$1 {
errors: Array<ValidationErrorDirective>;
fallback: ValidationFallbackDirective | undefined;
fallbackErrors: Array<FallbackError>;
}
type ViewModel$1 = {
shouldDisplayErrors: false;
} | {
shouldDisplayErrors: true;
errorsToDisplay: ErrorsToDisplay$1;
control: AbstractControl;
};
/**
* Component allowing to display validation error messages associated to a given form control, form group or form array.
* The control is provided using the `control` input of the component. If it's used inside an enclosing form group or
* form array, it can instead be provided using the `controlName` input of the component.
*
* Example usage where the control itself is being passed as input:
* ```
* <val-errors [control]="form.controls.birthDate">
* <ng-template valError="required">The birth date is mandatory</ng-template>
* <ng-template valError="max" let-error="error">The max value for the birth date is {{ error.max | number }}</ng-template>
* </val-errors>
* ```
*
* Example usage where the control name is being passed as input:
* ```
* <val-errors controlName="birthDate">
* <ng-template valError="required">The birth date is mandatory</ng-template>
* <ng-template valError="max" let-error="error">The max value for the birth date is {{ error.max | number }}</ng-template>
* </val-errors>
* ```
*
* This component, if the control is invalid, displays its validation errors using the provided templates.
* The templates, as shown in the above example, have access to the validation error itself.
*
* The label of the control can also be provided as input, and then used in the templates:
* ```
* <val-errors controlName="birthDate" label="the birth date">
* <ng-template valError="required" let-label>{{ label }} is mandatory</ng-template>
* <ng-template valError="max" let-error="error" let-label>The max value for {{ label }} is {{ error.max | number }}</ng-template>
* </val-errors>
* ```
*
* The component‘s behavior is configured globally by the Config service (see its documentation for more details). It can
* - display the first error, or all the errors
* - add CSS classes to its host `<val-errors>` element
* - add CSS classes to each error message element being displayed
* - choose when to display the errors (dirty, touched, touched and submitted, etc.)
*
* Global, default templates can be defined (and used by this component) using the default validation errors directive
* (see its documentation for details). So, if the default error messages are defined and sufficient for a given control, all you
* need is
*
* ```
* <val-errors controlName="birthDate"></val-errors>
* ```
*
* or, if the default templates expect a label:
*
* ```
* <val-errors controlName="birthDate" label="the birth date"></val-errors>
* ```
*
* If, however, you want to override one or several error messages by custom ones, you can do so by simply defining them inside the
* component:
*
* ```
* <val-errors controlName="birthDate" label="the birth date">
* <ng-template valError="max">You're too young, sorry</ng-template>
* </val-errors>
* ```
*
* A fallback template can also be provided. This fallback template is used for all the errors that exist on the form control
* but are not handled by any of the specific error templates:
* ```
* <val-errors controlName="birthDate" label="the birth date">
* <ng-template valError="max">You're too young, sorry</ng-template>
* <ng-template valFallback let-label let-type="type" let-error="error">{{ label }} has an unhandled error of type {{ type }}: {{ error | json }}</ng-template>
* </val-errors>
* ```
* Note that, the fallback template can also be defined in the default validation errors directive (see its documentation for details).
* If a fallback template is defined inside `val-errors`, it overrides the default fallback.
*
* If an error is present on the control, but doesn't have any template, default template or fallback template defined for its type,
* then it's not displayed. If the control is valid, or if none of the errors of the component has a matching template or default template,
* then this component itself is hidden.
*/
declare class ValidationErrorsComponent implements DoCheck {
/**
* The FormControl, FormGroup or FormArray containing the validation errors.
* If set, the controlName input is ignored
*/
readonly control: i0.InputSignal<AbstractControl<any, any, any> | null>;
/**
* The name (or the index, in case it's contained in a FormArray) of the FormControl, FormGroup or FormArray containing the validation
* errors.
* Ignored if the control input is set, and only usable if the control to validate is part of a control container
*/
readonly controlName: i0.InputSignal<string | number | null>;
/**
* The label of the field, exposed to templates so they can use it in the error message.
*/
readonly label: i0.InputSignal<string | null>;
/**
* The list of validation error directives (i.e. <ng-template valError="...">) contained inside the component element.
*/
readonly errorDirectives: Signal<readonly ValidationErrorDirective[]>;
/**
* The validation fallback directive (i.e. <ng-template valFallback>) contained inside the component element.
*/
readonly fallbackDirective: Signal<ValidationFallbackDirective | undefined>;
/**
* The Config service instance, defining the behavior of this component
*/
private readonly config;
readonly errorsClasses: string;
readonly errorClasses: string;
private readonly validationState;
/**
* The DefaultValidationErrors service instance, holding the default error templates,
* optionally defined by using the default validation errors directive
*/
private readonly defaultValidationErrors;
/**
* The control container, if it exists, as one of the 4 form group or form array directives that can "wrap" the control.
* It's injected so that we can know if it exists and, if it does, if its form directive has been submitted or not:
* the config service shouldDisplayErrors function can choose (and does by default) to use that information.
*/
private readonly controlContainer;
readonly vm: Signal<ViewModel$1>;
ngDoCheck(): void;
private shouldDisplayErrors;
private findErrorsToDisplay;
private findActualControl;
private hasDisplayableError;
static ɵfac: i0.ɵɵFactoryDeclaration<ValidationErrorsComponent, never>;
static ɵcmp: i0.ɵɵComponentDeclaration<ValidationErrorsComponent, "val-errors", never, { "control": { "alias": "control"; "required": false; "isSignal": true; }; "controlName": { "alias": "controlName"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; }, {}, ["errorDirectives", "fallbackDirective"], never, true, never>;
}
interface ErrorWithDirective {
error: ValidationError.WithField;
directive: ValidationErrorDirective;
}
interface ErrorsToDisplay {
errors: Array<ErrorWithDirective>;
fallback: ValidationFallbackDirective | undefined;
fallbackErrors: Array<ValidationError.WithField>;
}
type ViewModel = {
shouldDisplayErrors: false;
} | {
shouldDisplayErrors: true;
errorsToDisplay: ErrorsToDisplay;
};
/**
* **Experimental**
*
* Component allowing to display validation error messages associated to a given field of a signal form.
* The control is provided using the `forField` input of the component.
*
* Example usage:
* ```
* <val-signal-errors [forField]="form.birthYear">
* <ng-template valError="required">The birth year is mandatory</ng-template>
* <ng-template valError="max" let-error="error">The max value for the birth year is {{ error.max | number }}</ng-template>
* </val-errors>
* ```
*
* This component, if the control is invalid, displays its validation errors using the provided templates.
* The templates, as shown in the above example, have access to the validation error itself.
*
* The label of the control can also be provided as input, and then used in the templates:
* ```
* <val-signal-errors [forField]="form.birthYear" label="the birth year">
* <ng-template valError="required" let-label>{{ label }} is mandatory</ng-template>
* <ng-template valError="max" let-error="error" let-label>The max value for {{ label }} is {{ error.max | number }}</ng-template>
* </val-signal-errors>
* ```
*
* The component‘s behavior is configured globally by the Config service (see its documentation for more details). It can
* - display the first error, or all the errors
* - add CSS classes to its host `<val-errors>` element
* - add CSS classes to each error message element being displayed
* - choose when to display the errors (dirty, touched, etc.)
*
* Global, default templates can be defined (and used by this component) using the default validation errors directive
* (see its documentation for details). So, if the default error messages are defined and sufficient for a given control, all you
* need is
*
* ```
* <val-signal-errors [forField]="form.birthYear" />
* ```
*
* or, if the default templates expect a label:
*
* ```
* <val-signal-errors [forField]="form.birthYear" label="the birth year" />
* ```
*
* If, however, you want to override one or several error messages by custom ones, you can do so by simply defining them inside the
* component:
*
* ```
* <val-signal-errors [forField]="form.birthYear" label="the birth year">
* <ng-template valError="max">You're too young, sorry</ng-template>
* </val-signal-errors>
* ```
*
* A fallback template can also be provided. This fallback template is used for all the errors that exist on the form control
* but are not handled by any of the specific error templates:
* ```
* <val-signal-errors [forField]="form.birthYear" label="the birth year">
* <ng-template valError="max">You're too young, sorry</ng-template>
* <ng-template valFallback let-label let-type="type" let-error="error">{{ label }} has an unhandled error of kind {{ type }}: {{ error | json }}</ng-template>
* </val-signal-errors>
* ```
* Note that, the fallback template can also be defined in the default validation errors directive (see its documentation for details).
* If a fallback template is defined inside `val-signal-errors`, it overrides the default fallback.
*
* If an error is present on the field, but doesn't have any template, default template or fallback template defined for its type,
* then it's not displayed. If the field is valid, or if none of the errors of the component has a matching template or default template,
* then this component itself is hidden.
*/
declare class ValidationSignalErrorsComponent {
/**
* The FieldTree containing the validation errors.
*/
readonly field: i0.InputSignal<FieldTree<unknown>>;
/**
* The label of the field, exposed to templates so they can use it in the error message.
*/
readonly label: i0.InputSignal<string | null>;
/**
* The list of validation error directives (i.e. <ng-template valError="...">) contained inside the component element.
*/
readonly errorDirectives: Signal<readonly ValidationErrorDirective[]>;
/**
* The validation fallback directive (i.e. <ng-template valFallback>) contained inside the component element.
*/
readonly fallbackDirective: Signal<ValidationFallbackDirective | undefined>;
/**
* The Config service instance, defining the behavior of this component
*/
private readonly config;
readonly errorsClasses: string;
readonly errorClasses: string;
/**
* The DefaultValidationErrors service instance, holding the default error templates,
* optionally defined by using the default validation errors directive
*/
private readonly defaultValidationErrors;
private readonly hasDisplayableError;
private readonly shouldDisplayErrors;
readonly vm: Signal<ViewModel>;
private findErrorsToDisplay;
static ɵfac: i0.ɵɵFactoryDeclaration<ValidationSignalErrorsComponent, never>;
static ɵcmp: i0.ɵɵComponentDeclaration<ValidationSignalErrorsComponent, "val-signal-errors", never, { "field": { "alias": "forField"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; }, {}, ["errorDirectives", "fallbackDirective"], never, true, never>;
}
/**
* The display mode of the validation errors. For a given control, either all the validation errors
* are displayed, or only the first one.
*/
declare enum DisplayMode {
ALL = 0,
ONE = 1
}
/**
* The configuration service used by the validation errors component to apply common rules for all
* form controls.
*
* To change its default behavior, you can either inject this service in your root module or component and mutate it,
* or define your own implementation and provide it.
*/
declare class ValdemortConfig {
/**
* The display mode of the errors. The default value is ALL, meaning that all the errors existing on a control
* (and which have an error template defined) are displayed.
*/
displayMode: DisplayMode;
/**
* Specifies one or several CSS classes (separated by a white space) that are automatically added to the
* validation errors element. This can be useful to reuse a standard CSS class of your CSS framework (like
* .invalid-feedback in BootStrap), rather than styling the val-errors element itself.
*
* The default value is null (no class is added).
*/
errorsClasses: string | null;
/**
* Specifies one or several CSS classes (separated by a white space) that are automatically added to the
* each validation error message element. This can be useful to reuse a standard CSS class of your CSS framework
* rather than styling the div element itself.
*
* The default value is null (no class is added).
*/
errorClasses: string | null;
/**
* Specifies when error messages should be displayed based on the state of the control itself (touched, dirty, etc.)
* and on the state of the form directive containing it (if any). This function is only called if the control is invalid
* in the first place: if it's valid, errors are never displayed.
*
* The default value of this function returns true if the control is touched, or if the form (if any) is submitted.
*/
shouldDisplayErrors: (control: AbstractControl, form: NgForm | FormGroupDirective | undefined) => boolean;
/**
* **Experimental**
*
* Specifies when error messages should be displayed based on the state of the field (touched, dirty, etc.).
* This function must be reactive (i.e. it must return its value by reading signals).
* Note that if the field is valid, errors are never displayed, whatever ths function returns.
*
* The default value of this function returns true if the field is touched.
*/
shouldDisplayFieldErrors: (fieldState: FieldState<unknown, string | number>) => boolean;
/**
* Specifies if the library should throw an error when a control is not found.
* For example, this can happen if a typo was made in the `controlName`.
* If the check is enabled, then an error will be thrown in such a case.
* Otherwise, the error is silently ignored.
*
* The default value of this function returns false, thus disabling the check.
*
* You can enable the check by giving it a function that returns true,
* or you can enable it only in development for example with:
* `config.shouldThrowOnMissingControl = () => !environment.production`
*/
shouldThrowOnMissingControl: () => boolean;
static ɵfac: i0.ɵɵFactoryDeclaration<ValdemortConfig, never>;
static ɵprov: i0.ɵɵInjectableDeclaration<ValdemortConfig>;
}
declare class ValdemortModule {
static ɵfac: i0.ɵɵFactoryDeclaration<ValdemortModule, never>;
static ɵmod: i0.ɵɵNgModuleDeclaration<ValdemortModule, never, [typeof ValidationErrorsComponent, typeof ValidationSignalErrorsComponent, typeof ValidationErrorDirective, typeof ValidationFallbackDirective, typeof DefaultValidationErrorsDirective], [typeof ValidationErrorsComponent, typeof ValidationSignalErrorsComponent, typeof ValidationErrorDirective, typeof ValidationFallbackDirective, typeof DefaultValidationErrorsDirective]>;
static ɵinj: i0.ɵɵInjectorDeclaration<ValdemortModule>;
}
export { DefaultValidationErrorsDirective, DisplayMode, ValdemortConfig, ValdemortModule, ValidationErrorDirective, ValidationErrorsComponent, ValidationFallbackDirective, ValidationSignalErrorsComponent };