Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
218 changes: 181 additions & 37 deletions packages/forms/src/validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,37 +18,39 @@ function isEmptyInputValue(value: any): boolean {
}

/**
* Providers for validators to be used for `FormControl`s in a form.
* @description
* An `InjectionToken` for registering additional synchronous validators used with `AbstractControl`s.
*
* Provide this using `multi: true` to add validators.
*
* ### Example
* @see `NG_ASYNC_VALIDATORS`
*
* @usageNotes
*
* ### Providing a custom validator
*
* The following example registers a custom validator directive. Adding the validator to the
* existing collection of validators requires the `multi: true` option.
*
* ```typescript
* @Directive({
* selector: '[custom-validator]',
* selector: '[customValidator]',
* providers: [{provide: NG_VALIDATORS, useExisting: CustomValidatorDirective, multi: true}]
* })

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While we're here, do you mind updating the selector to follow latest conventions? i.e. [customValidator] rather than [custom-validator].

* class CustomValidatorDirective implements Validator {
* validate(control: AbstractControl): ValidationErrors | null {
* return {"custom": true};
* return { 'custom': true };
* }
* }
* ```
*
*
*/
export const NG_VALIDATORS = new InjectionToken<Array<Validator|Function>>('NgValidators');

/**
* Providers for asynchronous validators to be used for `FormControl`s
* in a form.
*
* Provide this using `multi: true` to add validators.
*
* See `NG_VALIDATORS` for more details.
*
* @description
* An `InjectionToken` for registering additional asynchronous validators used with `AbstractControl`s.
*
* @see `NG_VALIDATORS`
*
*/
export const NG_ASYNC_VALIDATORS =
new InjectionToken<Array<Validator|Function>>('NgAsyncValidators');
Expand All @@ -57,24 +59,34 @@ const EMAIL_REGEXP =
/^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+(\.[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/;

/**
* Provides a set of validators used by form controls.
* @description
* Provides a set of built-in validators that can be used by form controls.
*
* A validator is a function that processes a `FormControl` or collection of
* controls and returns a map of errors. A null map means that validation has passed.
*
* ### Example
*
* ```typescript
* var loginControl = new FormControl("", Validators.required)
* ```
*
* controls and returns an error map or null. A null map means that validation has passed.
*
* @see [Form Validation](/guide/form-validation)
*
*/
export class Validators {
/**
* Validator that requires controls to have a value greater than a number.
*`min()` exists only as a function, not as a directive. For example,
* `control = new FormControl('', Validators.min(3));`.
* @description
* Validator that requires the control's value to be greater than or equal to the provided number.
* The validator exists only as a function and not as a directive.
*
* @usageNotes
*
* ### Validate against a minimum of 3
*
* ```typescript
* const control = new FormControl(2, Validators.min(3));
*
* console.log(control.errors); // {min: {min: 3, actual: 2}}
* ```
*
* @returns A validator function that returns an error map with the
* `min` property if the validation check fails, otherwise `null`.
*
*/
static min(min: number): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
Expand All @@ -89,9 +101,23 @@ export class Validators {
}

/**
* Validator that requires controls to have a value less than a number.
* `max()` exists only as a function, not as a directive. For example,
* `control = new FormControl('', Validators.max(15));`.
* @description
* Validator that requires the control's value to be less than or equal to the provided number.
* The validator exists only as a function and not as a directive.
*
* @usageNotes
*
* ### Validate against a maximum of 15
*
* ```typescript
* const control = new FormControl(16, Validators.max(15));
*
* console.log(control.errors); // {max: {max: 15, actual: 16}}
* ```
*
* @returns A validator function that returns an error map with the
* `max` property if the validation check fails, otherwise `null`.
*
*/
static max(max: number): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
Expand All @@ -106,21 +132,66 @@ export class Validators {
}

/**
* Validator that requires controls to have a non-empty value.
* @description
* Validator that requires the control have a non-empty value.
*
* @usageNotes
*
* ### Validate that the field is non-empty
*
* ```typescript
* const control = new FormControl('', Validators.required);
*
* console.log(control.errors); // {required: true}
* ```
*
* @returns An error map with the `required` property
* if the validation check fails, otherwise `null`.
*
*/
static required(control: AbstractControl): ValidationErrors|null {
return isEmptyInputValue(control.value) ? {'required': true} : null;
}

/**
* Validator that requires control value to be true.
* @description
* Validator that requires the control's value be true. This validator is commonly
* used for required checkboxes.
*
* @usageNotes
*
* ### Validate that the field value is true
*
* ```typescript
* const control = new FormControl('', Validators.requiredTrue);
*
* console.log(control.errors); // {required: true}
* ```
*
* @returns An error map that contains the `required` property
* set to `true` if the validation check fails, otherwise `null`.
*/
static requiredTrue(control: AbstractControl): ValidationErrors|null {
return control.value === true ? null : {'required': true};
}

/**
* Validator that performs email validation.
* @description
* Validator that requires the control's value pass an email validation test.
*
* @usageNotes
*
* ### Validate that the field matches a valid email pattern
*
* ```typescript
* const control = new FormControl('bad@', Validators.email);
*
* console.log(control.errors); // {email: true}
* ```
*
* @returns An error map with the `email` property
* if the validation check fails, otherwise `null`.
*
*/
static email(control: AbstractControl): ValidationErrors|null {
if (isEmptyInputValue(control.value)) {
Expand All @@ -130,7 +201,27 @@ export class Validators {
}

/**
* Validator that requires controls to have a value of a minimum length.
* @description
* Validator that requires the length of the control's value to be greater than or equal
* to the provided minimum length. This validator is also provided by default if you use the
* the HTML5 `minlength` attribute.
*
* @usageNotes
*
* ### Validate that the field has a minimum of 3 characters
*
* ```typescript
* const control = new FormControl('ng', Validators.minLength(3));
*
* console.log(control.errors); // {minlength: {requiredLength: 3, actualLength: 2}}
* ```
*
* ```html
* <input minlength="5">
* ```
*
* @returns A validator function that returns an error map with the
* `minlength` if the validation check fails, otherwise `null`.
*/
static minLength(minLength: number): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
Expand All @@ -145,7 +236,27 @@ export class Validators {
}

/**
* Validator that requires controls to have a value of a maximum length.
* @description
* Validator that requires the length of the control's value to be less than or equal
* to the provided maximum length. This validator is also provided by default if you use the
* the HTML5 `maxlength` attribute.
*
* @usageNotes
*
* ### Validate that the field has maximum of 5 characters
*
* ```typescript
* const control = new FormControl('Angular', Validators.maxLength(5));
*
* console.log(control.errors); // {maxlength: {requiredLength: 5, actualLength: 7}}
* ```
*
* ```html
* <input maxlength="5">
* ```
*
* @returns A validator function that returns an error map with the
* `maxlength` property if the validation check fails, otherwise `null`.
*/
static maxLength(maxLength: number): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
Expand All @@ -157,7 +268,27 @@ export class Validators {
}

/**
* Validator that requires a control to match a regex to its value.
* @description
* Validator that requires the control's value to match a regex pattern. This validator is also
* provided
* by default if you use the HTML5 `pattern` attribute.
*
* @usageNotes
*
* ### Validate that the field only contains letters or spaces
*
* ```typescript
* const control = new FormControl('1', Validators.pattern('[a-zA-Z ]*'));
*
* console.log(control.errors); // {pattern: {requiredPattern: '^[a-zA-Z ]*$', actualValue: '1'}}
* ```
*
* ```html
* <input pattern="[a-zA-Z ]*">
* ```
*
* @returns A validator function that returns an error map with the
* `pattern` property if the validation check fails, otherwise `null`.
*/
static pattern(pattern: string|RegExp): ValidatorFn {
if (!pattern) return Validators.nullValidator;
Expand Down Expand Up @@ -188,13 +319,18 @@ export class Validators {
}

/**
* No-op validator.
* @description
* Validator that performs no operation.
*/
static nullValidator(c: AbstractControl): ValidationErrors|null { return null; }

/**
* @description
* Compose multiple validators into a single function that returns the union
* of the individual error maps.
* of the individual error maps for the provided control.
*
* @returns A validator function that returns an error map with the
* merged error maps of the validators if the validation check fails, otherwise `null`.
*/
static compose(validators: null): null;
static compose(validators: (ValidatorFn|null|undefined)[]): ValidatorFn|null;
Expand All @@ -208,6 +344,14 @@ export class Validators {
};
}

/**
* @description
* Compose multiple async validators into a single function that returns the union
* of the individual error objects for the provided control.
*
* @returns A validator function that returns an error map with the
* merged error objects of the async validators if the validation check fails, otherwise `null`.
*/
static composeAsync(validators: (AsyncValidatorFn|null)[]): AsyncValidatorFn|null {
if (!validators) return null;
const presentValidators: AsyncValidatorFn[] = validators.filter(isPresent) as any;
Expand Down