2016-06-23 09:47:54 -07:00
|
|
|
/**
|
|
|
|
|
* @license
|
|
|
|
|
* Copyright Google Inc. All Rights Reserved.
|
|
|
|
|
*
|
|
|
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
|
|
|
* found in the LICENSE file at https://angular.io/license
|
|
|
|
|
*/
|
2017-02-21 03:26:51 +03:00
|
|
|
|
perf: switch angular to use StaticInjector instead of ReflectiveInjector
This change allows ReflectiveInjector to be tree shaken resulting
in not needed Reflect polyfil and smaller bundles.
Code savings for HelloWorld using Closure:
Reflective: bundle.js: 105,864(34,190 gzip)
Static: bundle.js: 154,889(33,555 gzip)
645( 2%)
BREAKING CHANGE:
`platformXXXX()` no longer accepts providers which depend on reflection.
Specifically the method signature when from `Provider[]` to
`StaticProvider[]`.
Example:
Before:
```
[
MyClass,
{provide: ClassA, useClass: SubClassA}
]
```
After:
```
[
{provide: MyClass, deps: [Dep1,...]},
{provide: ClassA, useClass: SubClassA, deps: [Dep1,...]}
]
```
NOTE: This only applies to platform creation and providers for the JIT
compiler. It does not apply to `@Compotent` or `@NgModule` provides
declarations.
Benchpress note: Previously Benchpress also supported reflective
provides, which now require static providers.
DEPRECATION:
- `ReflectiveInjector` is now deprecated as it will be remove. Use
`Injector.create` as a replacement.
closes #18496
2017-08-03 12:33:29 -07:00
|
|
|
import {Directive, Input, OnChanges, SimpleChanges, StaticProvider, forwardRef} from '@angular/core';
|
2018-02-27 17:06:06 -05:00
|
|
|
import {Observable} from 'rxjs';
|
perf: switch angular to use StaticInjector instead of ReflectiveInjector
This change allows ReflectiveInjector to be tree shaken resulting
in not needed Reflect polyfil and smaller bundles.
Code savings for HelloWorld using Closure:
Reflective: bundle.js: 105,864(34,190 gzip)
Static: bundle.js: 154,889(33,555 gzip)
645( 2%)
BREAKING CHANGE:
`platformXXXX()` no longer accepts providers which depend on reflection.
Specifically the method signature when from `Provider[]` to
`StaticProvider[]`.
Example:
Before:
```
[
MyClass,
{provide: ClassA, useClass: SubClassA}
]
```
After:
```
[
{provide: MyClass, deps: [Dep1,...]},
{provide: ClassA, useClass: SubClassA, deps: [Dep1,...]}
]
```
NOTE: This only applies to platform creation and providers for the JIT
compiler. It does not apply to `@Compotent` or `@NgModule` provides
declarations.
Benchpress note: Previously Benchpress also supported reflective
provides, which now require static providers.
DEPRECATION:
- `ReflectiveInjector` is now deprecated as it will be remove. Use
`Injector.create` as a replacement.
closes #18496
2017-08-03 12:33:29 -07:00
|
|
|
|
2016-06-08 15:36:24 -07:00
|
|
|
import {AbstractControl} from '../model';
|
2016-06-08 16:38:52 -07:00
|
|
|
import {NG_VALIDATORS, Validators} from '../validators';
|
2016-06-08 15:36:24 -07:00
|
|
|
|
perf: switch angular to use StaticInjector instead of ReflectiveInjector
This change allows ReflectiveInjector to be tree shaken resulting
in not needed Reflect polyfil and smaller bundles.
Code savings for HelloWorld using Closure:
Reflective: bundle.js: 105,864(34,190 gzip)
Static: bundle.js: 154,889(33,555 gzip)
645( 2%)
BREAKING CHANGE:
`platformXXXX()` no longer accepts providers which depend on reflection.
Specifically the method signature when from `Provider[]` to
`StaticProvider[]`.
Example:
Before:
```
[
MyClass,
{provide: ClassA, useClass: SubClassA}
]
```
After:
```
[
{provide: MyClass, deps: [Dep1,...]},
{provide: ClassA, useClass: SubClassA, deps: [Dep1,...]}
]
```
NOTE: This only applies to platform creation and providers for the JIT
compiler. It does not apply to `@Compotent` or `@NgModule` provides
declarations.
Benchpress note: Previously Benchpress also supported reflective
provides, which now require static providers.
DEPRECATION:
- `ReflectiveInjector` is now deprecated as it will be remove. Use
`Injector.create` as a replacement.
closes #18496
2017-08-03 12:33:29 -07:00
|
|
|
|
2018-08-27 15:37:47 -05:00
|
|
|
/**
|
|
|
|
|
* @description
|
2018-11-01 13:51:37 -05:00
|
|
|
* Defines the map of errors returned from failed validation checks.
|
2018-08-27 15:37:47 -05:00
|
|
|
*
|
2018-10-19 12:12:20 +01:00
|
|
|
* @publicApi
|
2018-08-27 15:37:47 -05:00
|
|
|
*/
|
2017-02-23 20:53:29 +03:00
|
|
|
export type ValidationErrors = {
|
|
|
|
|
[key: string]: any
|
|
|
|
|
};
|
|
|
|
|
|
2016-06-08 15:36:24 -07:00
|
|
|
/**
|
2018-08-27 15:37:47 -05:00
|
|
|
* @description
|
|
|
|
|
* An interface implemented by classes that perform synchronous validation.
|
2016-06-08 15:36:24 -07:00
|
|
|
*
|
2018-08-27 15:37:47 -05:00
|
|
|
* @usageNotes
|
|
|
|
|
*
|
|
|
|
|
* ### Provide a custom validator
|
|
|
|
|
*
|
|
|
|
|
* The following example implements the `Validator` interface to create a
|
|
|
|
|
* validator directive with a custom error key.
|
2016-06-08 15:36:24 -07:00
|
|
|
*
|
|
|
|
|
* ```typescript
|
|
|
|
|
* @Directive({
|
2018-09-17 14:36:00 -05:00
|
|
|
* selector: '[customValidator]',
|
2016-06-08 15:36:24 -07:00
|
|
|
* providers: [{provide: NG_VALIDATORS, useExisting: CustomValidatorDirective, multi: true}]
|
|
|
|
|
* })
|
|
|
|
|
* class CustomValidatorDirective implements Validator {
|
2018-09-20 15:18:14 +01:00
|
|
|
* validate(control: AbstractControl): ValidationErrors|null {
|
2018-08-27 15:37:47 -05:00
|
|
|
* return {'custom': true};
|
2016-06-08 15:36:24 -07:00
|
|
|
* }
|
|
|
|
|
* }
|
|
|
|
|
* ```
|
2018-10-19 17:36:24 +01:00
|
|
|
*
|
|
|
|
|
* @publicApi
|
2016-06-08 15:36:24 -07:00
|
|
|
*/
|
2016-08-29 11:33:49 -07:00
|
|
|
export interface Validator {
|
2018-08-27 15:37:47 -05:00
|
|
|
/**
|
|
|
|
|
* @description
|
2018-09-17 14:36:00 -05:00
|
|
|
* Method that performs synchronous validation against the provided control.
|
2018-08-27 15:37:47 -05:00
|
|
|
*
|
2018-11-01 13:51:37 -05:00
|
|
|
* @param control The control to validate against.
|
2018-08-27 15:37:47 -05:00
|
|
|
*
|
|
|
|
|
* @returns A map of validation errors if validation fails,
|
|
|
|
|
* otherwise null.
|
|
|
|
|
*/
|
2018-09-20 15:18:14 +01:00
|
|
|
validate(control: AbstractControl): ValidationErrors|null;
|
2018-08-27 15:37:47 -05:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @description
|
|
|
|
|
* Registers a callback function to call when the validator inputs change.
|
|
|
|
|
*
|
|
|
|
|
* @param fn The callback function
|
|
|
|
|
*/
|
2016-09-09 14:09:11 -07:00
|
|
|
registerOnValidatorChange?(fn: () => void): void;
|
2016-08-29 11:33:49 -07:00
|
|
|
}
|
2016-06-08 15:36:24 -07:00
|
|
|
|
2018-08-27 15:37:47 -05:00
|
|
|
/**
|
|
|
|
|
* @description
|
|
|
|
|
* An interface implemented by classes that perform asynchronous validation.
|
|
|
|
|
*
|
|
|
|
|
* @usageNotes
|
|
|
|
|
*
|
|
|
|
|
* ### Provide a custom async validator directive
|
|
|
|
|
*
|
|
|
|
|
* The following example implements the `AsyncValidator` interface to create an
|
|
|
|
|
* async validator directive with a custom error key.
|
|
|
|
|
*
|
|
|
|
|
* ```typescript
|
|
|
|
|
* import { of as observableOf } from 'rxjs';
|
|
|
|
|
*
|
|
|
|
|
* @Directive({
|
2018-09-17 14:36:00 -05:00
|
|
|
* selector: '[customAsyncValidator]',
|
2018-08-27 15:37:47 -05:00
|
|
|
* providers: [{provide: NG_ASYNC_VALIDATORS, useExisting: CustomAsyncValidatorDirective, multi:
|
|
|
|
|
* true}]
|
|
|
|
|
* })
|
|
|
|
|
* class CustomAsyncValidatorDirective implements AsyncValidator {
|
2018-09-20 15:18:14 +01:00
|
|
|
* validate(control: AbstractControl): Observable<ValidationErrors|null> {
|
2018-08-27 15:37:47 -05:00
|
|
|
* return observableOf({'custom': true});
|
|
|
|
|
* }
|
|
|
|
|
* }
|
|
|
|
|
* ```
|
|
|
|
|
*
|
2018-10-19 12:12:20 +01:00
|
|
|
* @publicApi
|
2018-08-27 15:37:47 -05:00
|
|
|
*/
|
2017-02-21 03:26:51 +03:00
|
|
|
export interface AsyncValidator extends Validator {
|
2018-08-27 15:37:47 -05:00
|
|
|
/**
|
|
|
|
|
* @description
|
2018-09-17 14:36:00 -05:00
|
|
|
* Method that performs async validation against the provided control.
|
2018-08-27 15:37:47 -05:00
|
|
|
*
|
2018-11-01 13:51:37 -05:00
|
|
|
* @param control The control to validate against.
|
2018-08-27 15:37:47 -05:00
|
|
|
*
|
|
|
|
|
* @returns A promise or observable that resolves a map of validation errors
|
|
|
|
|
* if validation fails, otherwise null.
|
|
|
|
|
*/
|
2018-09-20 15:18:14 +01:00
|
|
|
validate(control: AbstractControl):
|
|
|
|
|
Promise<ValidationErrors|null>|Observable<ValidationErrors|null>;
|
2017-02-21 03:26:51 +03:00
|
|
|
}
|
|
|
|
|
|
2018-11-01 13:51:37 -05:00
|
|
|
/**
|
|
|
|
|
* @description
|
|
|
|
|
* Provider which adds `RequiredValidator` to the `NG_VALIDATORS` multi-provider list.
|
|
|
|
|
*/
|
perf: switch angular to use StaticInjector instead of ReflectiveInjector
This change allows ReflectiveInjector to be tree shaken resulting
in not needed Reflect polyfil and smaller bundles.
Code savings for HelloWorld using Closure:
Reflective: bundle.js: 105,864(34,190 gzip)
Static: bundle.js: 154,889(33,555 gzip)
645( 2%)
BREAKING CHANGE:
`platformXXXX()` no longer accepts providers which depend on reflection.
Specifically the method signature when from `Provider[]` to
`StaticProvider[]`.
Example:
Before:
```
[
MyClass,
{provide: ClassA, useClass: SubClassA}
]
```
After:
```
[
{provide: MyClass, deps: [Dep1,...]},
{provide: ClassA, useClass: SubClassA, deps: [Dep1,...]}
]
```
NOTE: This only applies to platform creation and providers for the JIT
compiler. It does not apply to `@Compotent` or `@NgModule` provides
declarations.
Benchpress note: Previously Benchpress also supported reflective
provides, which now require static providers.
DEPRECATION:
- `ReflectiveInjector` is now deprecated as it will be remove. Use
`Injector.create` as a replacement.
closes #18496
2017-08-03 12:33:29 -07:00
|
|
|
export const REQUIRED_VALIDATOR: StaticProvider = {
|
2016-06-08 15:36:24 -07:00
|
|
|
provide: NG_VALIDATORS,
|
2016-08-06 08:53:41 +02:00
|
|
|
useExisting: forwardRef(() => RequiredValidator),
|
2016-06-08 15:36:24 -07:00
|
|
|
multi: true
|
|
|
|
|
};
|
|
|
|
|
|
2018-11-01 13:51:37 -05:00
|
|
|
/**
|
|
|
|
|
* @description
|
|
|
|
|
* Provider which adds `CheckboxRequiredValidator` to the `NG_VALIDATORS` multi-provider list.
|
|
|
|
|
*/
|
perf: switch angular to use StaticInjector instead of ReflectiveInjector
This change allows ReflectiveInjector to be tree shaken resulting
in not needed Reflect polyfil and smaller bundles.
Code savings for HelloWorld using Closure:
Reflective: bundle.js: 105,864(34,190 gzip)
Static: bundle.js: 154,889(33,555 gzip)
645( 2%)
BREAKING CHANGE:
`platformXXXX()` no longer accepts providers which depend on reflection.
Specifically the method signature when from `Provider[]` to
`StaticProvider[]`.
Example:
Before:
```
[
MyClass,
{provide: ClassA, useClass: SubClassA}
]
```
After:
```
[
{provide: MyClass, deps: [Dep1,...]},
{provide: ClassA, useClass: SubClassA, deps: [Dep1,...]}
]
```
NOTE: This only applies to platform creation and providers for the JIT
compiler. It does not apply to `@Compotent` or `@NgModule` provides
declarations.
Benchpress note: Previously Benchpress also supported reflective
provides, which now require static providers.
DEPRECATION:
- `ReflectiveInjector` is now deprecated as it will be remove. Use
`Injector.create` as a replacement.
closes #18496
2017-08-03 12:33:29 -07:00
|
|
|
export const CHECKBOX_REQUIRED_VALIDATOR: StaticProvider = {
|
2016-12-10 13:44:04 +03:00
|
|
|
provide: NG_VALIDATORS,
|
|
|
|
|
useExisting: forwardRef(() => CheckboxRequiredValidator),
|
|
|
|
|
multi: true
|
|
|
|
|
};
|
|
|
|
|
|
2017-04-06 09:41:10 -06:00
|
|
|
|
2016-06-08 15:36:24 -07:00
|
|
|
/**
|
2018-11-01 13:51:37 -05:00
|
|
|
* @description
|
|
|
|
|
* A directive that adds the `required` validator to any controls marked with the
|
|
|
|
|
* `required` attribute. The directive is provided with the `NG_VALIDATORS` multi-provider list.
|
|
|
|
|
*
|
|
|
|
|
* @see [Form Validation](guide/form-validation)
|
2016-06-08 15:36:24 -07:00
|
|
|
*
|
2018-09-20 15:18:14 +01:00
|
|
|
* @usageNotes
|
2018-11-01 13:51:37 -05:00
|
|
|
*
|
|
|
|
|
* ### Adding a required validator using template-driven forms
|
2016-06-08 15:36:24 -07:00
|
|
|
*
|
|
|
|
|
* ```
|
2016-06-12 13:17:07 -07:00
|
|
|
* <input name="fullName" ngModel required>
|
2016-06-08 15:36:24 -07:00
|
|
|
* ```
|
|
|
|
|
*
|
2018-09-08 17:53:53 +01:00
|
|
|
* @ngModule FormsModule
|
|
|
|
|
* @ngModule ReactiveFormsModule
|
2018-10-19 17:36:24 +01:00
|
|
|
* @publicApi
|
2016-06-08 15:36:24 -07:00
|
|
|
*/
|
|
|
|
|
@Directive({
|
2016-12-10 13:44:04 +03:00
|
|
|
selector:
|
|
|
|
|
':not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]',
|
2016-08-06 08:53:41 +02:00
|
|
|
providers: [REQUIRED_VALIDATOR],
|
2016-11-16 05:48:34 +03:00
|
|
|
host: {'[attr.required]': 'required ? "" : null'}
|
2016-06-08 15:36:24 -07:00
|
|
|
})
|
2016-08-06 08:53:41 +02:00
|
|
|
export class RequiredValidator implements Validator {
|
2018-06-18 16:38:33 -07:00
|
|
|
// TODO(issue/24571): remove '!'.
|
|
|
|
|
private _required !: boolean;
|
|
|
|
|
// TODO(issue/24571): remove '!'.
|
|
|
|
|
private _onChange !: () => void;
|
2016-08-06 08:53:41 +02:00
|
|
|
|
2018-11-01 13:51:37 -05:00
|
|
|
/**
|
|
|
|
|
* @description
|
|
|
|
|
* Tracks changes to the required attribute bound to this directive.
|
|
|
|
|
*/
|
2016-08-06 08:53:41 +02:00
|
|
|
@Input()
|
2017-02-23 20:53:29 +03:00
|
|
|
get required(): boolean|string { return this._required; }
|
2016-08-06 08:53:41 +02:00
|
|
|
|
2017-02-23 20:53:29 +03:00
|
|
|
set required(value: boolean|string) {
|
2016-11-16 05:48:34 +03:00
|
|
|
this._required = value != null && value !== false && `${value}` !== 'false';
|
2016-08-29 11:33:49 -07:00
|
|
|
if (this._onChange) this._onChange();
|
|
|
|
|
}
|
2016-08-06 08:53:41 +02:00
|
|
|
|
2018-11-01 13:51:37 -05:00
|
|
|
/**
|
|
|
|
|
* @description
|
|
|
|
|
* Method that validates whether the control is empty.
|
|
|
|
|
* Returns the validation result if enabled, otherwise null.
|
|
|
|
|
*/
|
2018-09-20 15:18:14 +01:00
|
|
|
validate(control: AbstractControl): ValidationErrors|null {
|
|
|
|
|
return this.required ? Validators.required(control) : null;
|
2016-08-06 08:53:41 +02:00
|
|
|
}
|
2016-08-29 11:33:49 -07:00
|
|
|
|
2018-11-01 13:51:37 -05:00
|
|
|
/**
|
|
|
|
|
* @description
|
|
|
|
|
* Registers a callback function to call when the validator inputs change.
|
|
|
|
|
*
|
|
|
|
|
* @param fn The callback function
|
|
|
|
|
*/
|
2016-11-16 05:48:34 +03:00
|
|
|
registerOnValidatorChange(fn: () => void): void { this._onChange = fn; }
|
2016-06-08 15:36:24 -07:00
|
|
|
}
|
|
|
|
|
|
2017-04-06 09:41:10 -06:00
|
|
|
|
2016-12-10 13:44:04 +03:00
|
|
|
/**
|
|
|
|
|
* A Directive that adds the `required` validator to checkbox controls marked with the
|
2018-11-01 13:51:37 -05:00
|
|
|
* `required` attribute. The directive is provided with the `NG_VALIDATORS` multi-provider list.
|
|
|
|
|
*
|
|
|
|
|
* @see [Form Validation](guide/form-validation)
|
2016-12-10 13:44:04 +03:00
|
|
|
*
|
2018-09-20 15:18:14 +01:00
|
|
|
* @usageNotes
|
2018-11-01 13:51:37 -05:00
|
|
|
*
|
|
|
|
|
* ### Adding a required checkbox validator using template-driven forms
|
2016-12-10 13:44:04 +03:00
|
|
|
*
|
2018-11-01 13:51:37 -05:00
|
|
|
* The following example shows how to add a checkbox required validator to an input attached to an ngModel binding.
|
|
|
|
|
*
|
2016-12-10 13:44:04 +03:00
|
|
|
* ```
|
|
|
|
|
* <input type="checkbox" name="active" ngModel required>
|
|
|
|
|
* ```
|
|
|
|
|
*
|
2018-10-19 12:12:20 +01:00
|
|
|
* @publicApi
|
2018-09-08 17:53:53 +01:00
|
|
|
* @ngModule FormsModule
|
|
|
|
|
* @ngModule ReactiveFormsModule
|
2016-12-10 13:44:04 +03:00
|
|
|
*/
|
|
|
|
|
@Directive({
|
|
|
|
|
selector:
|
|
|
|
|
'input[type=checkbox][required][formControlName],input[type=checkbox][required][formControl],input[type=checkbox][required][ngModel]',
|
|
|
|
|
providers: [CHECKBOX_REQUIRED_VALIDATOR],
|
|
|
|
|
host: {'[attr.required]': 'required ? "" : null'}
|
|
|
|
|
})
|
|
|
|
|
export class CheckboxRequiredValidator extends RequiredValidator {
|
2018-11-01 13:51:37 -05:00
|
|
|
/**
|
|
|
|
|
* @description
|
|
|
|
|
* Method that validates whether or not the checkbox has been checked.
|
|
|
|
|
* Returns the validation result if enabled, otherwise null.
|
|
|
|
|
*/
|
2018-09-20 15:18:14 +01:00
|
|
|
validate(control: AbstractControl): ValidationErrors|null {
|
|
|
|
|
return this.required ? Validators.requiredTrue(control) : null;
|
2016-12-10 13:44:04 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-29 20:07:02 +03:00
|
|
|
/**
|
2018-11-01 13:51:37 -05:00
|
|
|
* @description
|
|
|
|
|
* Provider which adds `EmailValidator` to the `NG_VALIDATORS` multi-provider list.
|
2016-12-29 20:07:02 +03:00
|
|
|
*/
|
|
|
|
|
export const EMAIL_VALIDATOR: any = {
|
|
|
|
|
provide: NG_VALIDATORS,
|
|
|
|
|
useExisting: forwardRef(() => EmailValidator),
|
|
|
|
|
multi: true
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
2018-11-01 13:51:37 -05:00
|
|
|
* A directive that adds the `email` validator to controls marked with the
|
|
|
|
|
* `email` attribute. The directive is provided with the `NG_VALIDATORS` multi-provider list.
|
|
|
|
|
*
|
|
|
|
|
* @see [Form Validation](guide/form-validation)
|
2016-12-29 20:07:02 +03:00
|
|
|
*
|
2018-09-20 15:18:14 +01:00
|
|
|
* @usageNotes
|
2018-11-01 13:51:37 -05:00
|
|
|
*
|
|
|
|
|
* ### Adding an email validator
|
2016-12-29 20:07:02 +03:00
|
|
|
*
|
2018-11-01 13:51:37 -05:00
|
|
|
* The following example shows how to add an email validator to an input attached to an ngModel binding.
|
|
|
|
|
*
|
2016-12-29 20:07:02 +03:00
|
|
|
* ```
|
|
|
|
|
* <input type="email" name="email" ngModel email>
|
|
|
|
|
* <input type="email" name="email" ngModel email="true">
|
|
|
|
|
* <input type="email" name="email" ngModel [email]="true">
|
|
|
|
|
* ```
|
|
|
|
|
*
|
2018-10-19 12:12:20 +01:00
|
|
|
* @publicApi
|
2018-09-08 17:53:53 +01:00
|
|
|
* @ngModule FormsModule
|
|
|
|
|
* @ngModule ReactiveFormsModule
|
2016-12-29 20:07:02 +03:00
|
|
|
*/
|
|
|
|
|
@Directive({
|
|
|
|
|
selector: '[email][formControlName],[email][formControl],[email][ngModel]',
|
|
|
|
|
providers: [EMAIL_VALIDATOR]
|
|
|
|
|
})
|
|
|
|
|
export class EmailValidator implements Validator {
|
2018-06-18 16:38:33 -07:00
|
|
|
// TODO(issue/24571): remove '!'.
|
|
|
|
|
private _enabled !: boolean;
|
|
|
|
|
// TODO(issue/24571): remove '!'.
|
|
|
|
|
private _onChange !: () => void;
|
2016-12-29 20:07:02 +03:00
|
|
|
|
2018-11-01 13:51:37 -05:00
|
|
|
/**
|
|
|
|
|
* @description
|
|
|
|
|
* Tracks changes to the email attribute bound to this directive.
|
|
|
|
|
*/
|
2016-12-29 20:07:02 +03:00
|
|
|
@Input()
|
|
|
|
|
set email(value: boolean|string) {
|
|
|
|
|
this._enabled = value === '' || value === true || value === 'true';
|
|
|
|
|
if (this._onChange) this._onChange();
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-01 13:51:37 -05:00
|
|
|
/**
|
|
|
|
|
* @description
|
|
|
|
|
* Method that validates whether an email address is valid.
|
|
|
|
|
* Returns the validation result if enabled, otherwise null.
|
|
|
|
|
*/
|
2018-09-20 15:18:14 +01:00
|
|
|
validate(control: AbstractControl): ValidationErrors|null {
|
|
|
|
|
return this._enabled ? Validators.email(control) : null;
|
2016-12-29 20:07:02 +03:00
|
|
|
}
|
|
|
|
|
|
2018-11-01 13:51:37 -05:00
|
|
|
/**
|
|
|
|
|
* @description
|
|
|
|
|
* Registers a callback function to call when the validator inputs change.
|
|
|
|
|
*
|
|
|
|
|
* @param fn The callback function
|
|
|
|
|
*/
|
2016-12-29 20:07:02 +03:00
|
|
|
registerOnValidatorChange(fn: () => void): void { this._onChange = fn; }
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-19 17:36:24 +01:00
|
|
|
/**
|
2018-11-01 13:51:37 -05:00
|
|
|
* @description
|
|
|
|
|
* A function that receives a control and synchronously returns a map of
|
|
|
|
|
* validation errors if present, otherwise null.
|
|
|
|
|
*
|
2018-10-19 17:36:24 +01:00
|
|
|
* @publicApi
|
|
|
|
|
*/
|
2018-09-20 15:18:14 +01:00
|
|
|
export interface ValidatorFn { (control: AbstractControl): ValidationErrors|null; }
|
2016-06-27 12:27:23 -07:00
|
|
|
|
2018-10-19 17:36:24 +01:00
|
|
|
/**
|
2018-11-01 13:51:37 -05:00
|
|
|
* @description
|
|
|
|
|
* A function that receives a control and returns a Promise or observable
|
|
|
|
|
* that emits validation errors if present, otherwise null.
|
|
|
|
|
*
|
2018-10-19 17:36:24 +01:00
|
|
|
* @publicApi
|
|
|
|
|
*/
|
2016-06-08 15:36:24 -07:00
|
|
|
export interface AsyncValidatorFn {
|
2018-09-20 15:18:14 +01:00
|
|
|
(control: AbstractControl): Promise<ValidationErrors|null>|Observable<ValidationErrors|null>;
|
2016-06-08 15:36:24 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2018-11-01 13:51:37 -05:00
|
|
|
* @description
|
|
|
|
|
* Provider which adds `MinLengthValidator` to the `NG_VALIDATORS` multi-provider list.
|
2016-06-08 15:36:24 -07:00
|
|
|
*/
|
2016-07-30 19:18:14 -07:00
|
|
|
export const MIN_LENGTH_VALIDATOR: any = {
|
2016-06-08 15:36:24 -07:00
|
|
|
provide: NG_VALIDATORS,
|
|
|
|
|
useExisting: forwardRef(() => MinLengthValidator),
|
|
|
|
|
multi: true
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
2018-11-01 13:51:37 -05:00
|
|
|
* A directive that adds minimum length validation to controls marked with the
|
|
|
|
|
* `minlength` attribute. The directive is provided with the `NG_VALIDATORS` mult-provider list.
|
|
|
|
|
*
|
|
|
|
|
* @see [Form Validation](guide/form-validation)
|
|
|
|
|
*
|
|
|
|
|
* @usageNotes
|
|
|
|
|
*
|
|
|
|
|
* ### Adding a minimum length validator
|
|
|
|
|
*
|
|
|
|
|
* The following example shows how to add a minimum length validator to an input attached to an
|
|
|
|
|
* ngModel binding.
|
|
|
|
|
*
|
|
|
|
|
* ```html
|
|
|
|
|
* <input name="firstName" ngModel minlength="4">
|
|
|
|
|
* ```
|
2016-06-08 15:36:24 -07:00
|
|
|
*
|
2018-09-08 17:53:53 +01:00
|
|
|
* @ngModule ReactiveFormsModule
|
2018-11-01 13:51:37 -05:00
|
|
|
* @ngModule FormsModule
|
2018-10-19 17:36:24 +01:00
|
|
|
* @publicApi
|
2016-06-08 15:36:24 -07:00
|
|
|
*/
|
|
|
|
|
@Directive({
|
2016-06-12 13:17:07 -07:00
|
|
|
selector: '[minlength][formControlName],[minlength][formControl],[minlength][ngModel]',
|
2016-08-06 08:53:41 +02:00
|
|
|
providers: [MIN_LENGTH_VALIDATOR],
|
2016-11-16 05:48:34 +03:00
|
|
|
host: {'[attr.minlength]': 'minlength ? minlength : null'}
|
2016-06-08 15:36:24 -07:00
|
|
|
})
|
2016-08-06 08:53:41 +02:00
|
|
|
export class MinLengthValidator implements Validator,
|
|
|
|
|
OnChanges {
|
2018-06-18 16:38:33 -07:00
|
|
|
// TODO(issue/24571): remove '!'.
|
|
|
|
|
private _validator !: ValidatorFn;
|
|
|
|
|
// TODO(issue/24571): remove '!'.
|
|
|
|
|
private _onChange !: () => void;
|
2016-06-08 15:36:24 -07:00
|
|
|
|
2018-11-01 13:51:37 -05:00
|
|
|
/**
|
|
|
|
|
* @description
|
|
|
|
|
* Tracks changes to the the minimum length bound to this directive.
|
|
|
|
|
*/
|
2018-06-18 16:38:33 -07:00
|
|
|
// TODO(issue/24571): remove '!'.
|
|
|
|
|
@Input() minlength !: string;
|
2016-08-06 08:53:41 +02:00
|
|
|
|
2018-11-01 13:51:37 -05:00
|
|
|
/**
|
|
|
|
|
* @description
|
|
|
|
|
* A lifecycle method called when the directive's inputs change. For internal use
|
|
|
|
|
* only.
|
|
|
|
|
*
|
|
|
|
|
* @param changes A object of key/value pairs for the set of changed inputs.
|
|
|
|
|
*/
|
2016-11-16 05:48:34 +03:00
|
|
|
ngOnChanges(changes: SimpleChanges): void {
|
|
|
|
|
if ('minlength' in changes) {
|
2016-08-06 08:53:41 +02:00
|
|
|
this._createValidator();
|
2016-08-29 11:33:49 -07:00
|
|
|
if (this._onChange) this._onChange();
|
2016-08-06 08:53:41 +02:00
|
|
|
}
|
2016-06-08 15:36:24 -07:00
|
|
|
}
|
|
|
|
|
|
2018-11-01 13:51:37 -05:00
|
|
|
/**
|
|
|
|
|
* @description
|
|
|
|
|
* Method that validates whether the value meets a minimum length
|
|
|
|
|
* requirement. Returns the validation result if enabled, otherwise null.
|
|
|
|
|
*/
|
2018-09-20 15:18:14 +01:00
|
|
|
validate(control: AbstractControl): ValidationErrors|null {
|
|
|
|
|
return this.minlength == null ? null : this._validator(control);
|
2016-08-06 08:53:41 +02:00
|
|
|
}
|
2016-08-29 11:33:49 -07:00
|
|
|
|
2018-11-01 13:51:37 -05:00
|
|
|
/**
|
|
|
|
|
* @description
|
|
|
|
|
* Registers a callback function to call when the validator inputs change.
|
|
|
|
|
*
|
|
|
|
|
* @param fn The callback function
|
|
|
|
|
*/
|
2016-11-16 05:48:34 +03:00
|
|
|
registerOnValidatorChange(fn: () => void): void { this._onChange = fn; }
|
|
|
|
|
|
|
|
|
|
private _createValidator(): void {
|
|
|
|
|
this._validator = Validators.minLength(parseInt(this.minlength, 10));
|
|
|
|
|
}
|
2016-06-08 15:36:24 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2018-11-01 13:51:37 -05:00
|
|
|
* @description
|
|
|
|
|
* Provider which adds `MaxLengthValidator` to the `NG_VALIDATORS` multi-provider list.
|
2016-06-08 15:36:24 -07:00
|
|
|
*/
|
2016-07-30 19:18:14 -07:00
|
|
|
export const MAX_LENGTH_VALIDATOR: any = {
|
2016-06-08 15:36:24 -07:00
|
|
|
provide: NG_VALIDATORS,
|
|
|
|
|
useExisting: forwardRef(() => MaxLengthValidator),
|
|
|
|
|
multi: true
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
2018-11-01 13:51:37 -05:00
|
|
|
* A directive that adds max length validation to controls marked with the
|
|
|
|
|
* `maxlength` attribute. The directive is provided with the `NG_VALIDATORS` multi-provider list.
|
|
|
|
|
*
|
|
|
|
|
* @see [Form Validation](guide/form-validation)
|
|
|
|
|
*
|
|
|
|
|
* @usageNotes
|
|
|
|
|
*
|
|
|
|
|
* ### Adding a maximum length validator
|
|
|
|
|
*
|
|
|
|
|
* The following example shows how to add a maximum length validator to an input attached to an
|
|
|
|
|
* ngModel binding.
|
|
|
|
|
*
|
|
|
|
|
* ```html
|
|
|
|
|
* <input name="firstName" ngModel maxlength="25">
|
|
|
|
|
* ```
|
2016-06-08 15:36:24 -07:00
|
|
|
*
|
2018-09-08 17:53:53 +01:00
|
|
|
* @ngModule ReactiveFormsModule
|
2018-11-01 13:51:37 -05:00
|
|
|
* @ngModule FormsModule
|
2018-10-19 17:36:24 +01:00
|
|
|
* @publicApi
|
2016-06-08 15:36:24 -07:00
|
|
|
*/
|
|
|
|
|
@Directive({
|
2016-06-12 13:17:07 -07:00
|
|
|
selector: '[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]',
|
2016-08-06 08:53:41 +02:00
|
|
|
providers: [MAX_LENGTH_VALIDATOR],
|
2016-11-16 05:48:34 +03:00
|
|
|
host: {'[attr.maxlength]': 'maxlength ? maxlength : null'}
|
2016-06-08 15:36:24 -07:00
|
|
|
})
|
2016-08-06 08:53:41 +02:00
|
|
|
export class MaxLengthValidator implements Validator,
|
|
|
|
|
OnChanges {
|
2018-06-18 16:38:33 -07:00
|
|
|
// TODO(issue/24571): remove '!'.
|
|
|
|
|
private _validator !: ValidatorFn;
|
|
|
|
|
// TODO(issue/24571): remove '!'.
|
|
|
|
|
private _onChange !: () => void;
|
2016-06-08 15:36:24 -07:00
|
|
|
|
2018-11-01 13:51:37 -05:00
|
|
|
/**
|
|
|
|
|
* @description
|
|
|
|
|
* Tracks changes to the the maximum length bound to this directive.
|
|
|
|
|
*/
|
2018-06-18 16:38:33 -07:00
|
|
|
// TODO(issue/24571): remove '!'.
|
|
|
|
|
@Input() maxlength !: string;
|
2016-08-06 08:53:41 +02:00
|
|
|
|
2018-11-01 13:51:37 -05:00
|
|
|
/**
|
|
|
|
|
* @description
|
|
|
|
|
* A lifecycle method called when the directive's inputs change. For internal use
|
|
|
|
|
* only.
|
|
|
|
|
*
|
|
|
|
|
* @param changes A object of key/value pairs for the set of changed inputs.
|
|
|
|
|
*/
|
2016-11-16 05:48:34 +03:00
|
|
|
ngOnChanges(changes: SimpleChanges): void {
|
|
|
|
|
if ('maxlength' in changes) {
|
2016-08-06 08:53:41 +02:00
|
|
|
this._createValidator();
|
2016-08-29 11:33:49 -07:00
|
|
|
if (this._onChange) this._onChange();
|
2016-08-06 08:53:41 +02:00
|
|
|
}
|
2016-06-08 15:36:24 -07:00
|
|
|
}
|
|
|
|
|
|
2018-11-01 13:51:37 -05:00
|
|
|
/**
|
|
|
|
|
* @description
|
|
|
|
|
* Method that validates whether the value exceeds
|
|
|
|
|
* the maximum length requirement.
|
|
|
|
|
*/
|
2018-09-20 15:18:14 +01:00
|
|
|
validate(control: AbstractControl): ValidationErrors|null {
|
|
|
|
|
return this.maxlength != null ? this._validator(control) : null;
|
2016-08-06 08:53:41 +02:00
|
|
|
}
|
2016-08-29 11:33:49 -07:00
|
|
|
|
2018-11-01 13:51:37 -05:00
|
|
|
/**
|
|
|
|
|
* @description
|
|
|
|
|
* Registers a callback function to call when the validator inputs change.
|
|
|
|
|
*
|
|
|
|
|
* @param fn The callback function
|
|
|
|
|
*/
|
2016-11-16 05:48:34 +03:00
|
|
|
registerOnValidatorChange(fn: () => void): void { this._onChange = fn; }
|
|
|
|
|
|
|
|
|
|
private _createValidator(): void {
|
|
|
|
|
this._validator = Validators.maxLength(parseInt(this.maxlength, 10));
|
|
|
|
|
}
|
2016-06-08 15:36:24 -07:00
|
|
|
}
|
|
|
|
|
|
2018-11-01 13:51:37 -05:00
|
|
|
/**
|
|
|
|
|
* @description
|
|
|
|
|
* Provider which adds `PatternValidator` to the `NG_VALIDATORS` multi-provider list.
|
|
|
|
|
*/
|
2016-07-30 19:18:14 -07:00
|
|
|
export const PATTERN_VALIDATOR: any = {
|
2016-06-08 15:36:24 -07:00
|
|
|
provide: NG_VALIDATORS,
|
|
|
|
|
useExisting: forwardRef(() => PatternValidator),
|
|
|
|
|
multi: true
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2018-11-01 13:51:37 -05:00
|
|
|
* @description
|
|
|
|
|
* A directive that adds regex pattern validation to controls marked with the
|
|
|
|
|
* `pattern` attribute. The regex must match the entire control value.
|
|
|
|
|
* The directive is provided with the `NG_VALIDATORS` multi-provider list.
|
|
|
|
|
*
|
|
|
|
|
* @see [Form Validation](guide/form-validation)
|
2016-06-08 15:36:24 -07:00
|
|
|
*
|
2018-09-20 15:18:14 +01:00
|
|
|
* @usageNotes
|
2016-06-08 15:36:24 -07:00
|
|
|
*
|
2018-11-01 13:51:37 -05:00
|
|
|
* ### Adding a pattern validator
|
2018-04-05 22:31:44 +01:00
|
|
|
*
|
2018-11-01 13:51:37 -05:00
|
|
|
* The following example shows how to add a pattern validator to an input attached to an
|
|
|
|
|
* ngModel binding.
|
|
|
|
|
*
|
|
|
|
|
* ```html
|
|
|
|
|
* <input name="firstName" ngModel pattern="[a-zA-Z ]*">
|
|
|
|
|
* ```
|
|
|
|
|
*
|
2018-09-08 17:53:53 +01:00
|
|
|
* @ngModule ReactiveFormsModule
|
2018-11-01 13:51:37 -05:00
|
|
|
* @ngModule FormsModule
|
2018-10-19 17:36:24 +01:00
|
|
|
* @publicApi
|
2016-06-08 15:36:24 -07:00
|
|
|
*/
|
|
|
|
|
@Directive({
|
2016-06-12 13:17:07 -07:00
|
|
|
selector: '[pattern][formControlName],[pattern][formControl],[pattern][ngModel]',
|
2016-08-06 08:53:41 +02:00
|
|
|
providers: [PATTERN_VALIDATOR],
|
2016-11-11 10:47:34 -08:00
|
|
|
host: {'[attr.pattern]': 'pattern ? pattern : null'}
|
2016-06-08 15:36:24 -07:00
|
|
|
})
|
2016-08-06 08:53:41 +02:00
|
|
|
export class PatternValidator implements Validator,
|
|
|
|
|
OnChanges {
|
2018-06-18 16:38:33 -07:00
|
|
|
// TODO(issue/24571): remove '!'.
|
|
|
|
|
private _validator !: ValidatorFn;
|
|
|
|
|
// TODO(issue/24571): remove '!'.
|
|
|
|
|
private _onChange !: () => void;
|
2016-06-08 15:36:24 -07:00
|
|
|
|
2018-11-01 13:51:37 -05:00
|
|
|
/**
|
|
|
|
|
* @description
|
|
|
|
|
* Tracks changes to the pattern bound to this directive.
|
|
|
|
|
*/
|
2018-06-18 16:38:33 -07:00
|
|
|
// TODO(issue/24571): remove '!'.
|
|
|
|
|
@Input() pattern !: string | RegExp;
|
2016-08-06 08:53:41 +02:00
|
|
|
|
2018-11-01 13:51:37 -05:00
|
|
|
/**
|
|
|
|
|
* @description
|
|
|
|
|
* A lifecycle method called when the directive's inputs change. For internal use
|
|
|
|
|
* only.
|
|
|
|
|
*
|
|
|
|
|
* @param changes A object of key/value pairs for the set of changed inputs.
|
|
|
|
|
*/
|
2016-11-16 05:48:34 +03:00
|
|
|
ngOnChanges(changes: SimpleChanges): void {
|
|
|
|
|
if ('pattern' in changes) {
|
2016-08-06 08:53:41 +02:00
|
|
|
this._createValidator();
|
2016-08-29 11:33:49 -07:00
|
|
|
if (this._onChange) this._onChange();
|
2016-08-06 08:53:41 +02:00
|
|
|
}
|
2016-06-08 15:36:24 -07:00
|
|
|
}
|
|
|
|
|
|
2018-11-01 13:51:37 -05:00
|
|
|
/**
|
|
|
|
|
* @description
|
|
|
|
|
* Method that validates whether the value matches the
|
|
|
|
|
* the pattern requirement.
|
|
|
|
|
*/
|
2018-09-20 15:18:14 +01:00
|
|
|
validate(control: AbstractControl): ValidationErrors|null { return this._validator(control); }
|
2016-11-16 05:48:34 +03:00
|
|
|
|
2018-11-01 13:51:37 -05:00
|
|
|
/**
|
|
|
|
|
* @description
|
|
|
|
|
* Registers a callback function to call when the validator inputs change.
|
|
|
|
|
*
|
|
|
|
|
* @param fn The callback function
|
|
|
|
|
*/
|
2016-11-16 05:48:34 +03:00
|
|
|
registerOnValidatorChange(fn: () => void): void { this._onChange = fn; }
|
2016-08-29 11:33:49 -07:00
|
|
|
|
2016-11-16 05:48:34 +03:00
|
|
|
private _createValidator(): void { this._validator = Validators.pattern(this.pattern); }
|
2016-06-08 15:36:24 -07:00
|
|
|
}
|