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
|
|
|
|
* Defines the map of errors returned from failed validation checks
|
|
|
|
*
|
|
|
|
* @experimental
|
|
|
|
*/
|
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
|
|
|
* }
|
|
|
|
* }
|
|
|
|
* ```
|
|
|
|
*/
|
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
|
|
|
*
|
|
|
|
* @param c The control to validate against.
|
|
|
|
*
|
|
|
|
* @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});
|
|
|
|
* }
|
|
|
|
* }
|
|
|
|
* ```
|
|
|
|
*
|
|
|
|
* @experimental
|
|
|
|
*/
|
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
|
|
|
*
|
|
|
|
* @param c The control to validate against.
|
|
|
|
*
|
|
|
|
* @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
|
|
|
}
|
|
|
|
|
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
|
|
|
|
};
|
|
|
|
|
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
|
|
|
/**
|
|
|
|
* A Directive that adds the `required` validator to any controls marked with the
|
2018-04-05 10:58:12 +01:00
|
|
|
* `required` attribute, via the `NG_VALIDATORS` binding.
|
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
|
|
|
* ### Example
|
|
|
|
*
|
|
|
|
* ```
|
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
|
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
|
|
|
|
|
|
|
@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-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
|
|
|
|
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-04-05 10:58:12 +01:00
|
|
|
* `required` attribute, via the `NG_VALIDATORS` binding.
|
2016-12-10 13:44:04 +03:00
|
|
|
*
|
2018-09-20 15:18:14 +01:00
|
|
|
* @usageNotes
|
2016-12-10 13:44:04 +03:00
|
|
|
* ### Example
|
|
|
|
*
|
|
|
|
* ```
|
|
|
|
* <input type="checkbox" name="active" ngModel required>
|
|
|
|
* ```
|
|
|
|
*
|
|
|
|
* @experimental
|
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-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-04-05 10:58:12 +01:00
|
|
|
* Provider which adds `EmailValidator` to `NG_VALIDATORS`.
|
2016-12-29 20:07:02 +03:00
|
|
|
*/
|
|
|
|
export const EMAIL_VALIDATOR: any = {
|
|
|
|
provide: NG_VALIDATORS,
|
|
|
|
useExisting: forwardRef(() => EmailValidator),
|
|
|
|
multi: true
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A Directive that adds the `email` validator to controls marked with the
|
2018-04-05 10:58:12 +01:00
|
|
|
* `email` attribute, via the `NG_VALIDATORS` binding.
|
2016-12-29 20:07:02 +03:00
|
|
|
*
|
2018-09-20 15:18:14 +01:00
|
|
|
* @usageNotes
|
2016-12-29 20:07:02 +03:00
|
|
|
* ### Example
|
|
|
|
*
|
|
|
|
* ```
|
|
|
|
* <input type="email" name="email" ngModel email>
|
|
|
|
* <input type="email" name="email" ngModel email="true">
|
|
|
|
* <input type="email" name="email" ngModel [email]="true">
|
|
|
|
* ```
|
|
|
|
*
|
|
|
|
* @experimental
|
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
|
|
|
|
|
|
|
@Input()
|
|
|
|
set email(value: boolean|string) {
|
|
|
|
this._enabled = value === '' || value === true || value === 'true';
|
|
|
|
if (this._onChange) this._onChange();
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
registerOnValidatorChange(fn: () => void): void { this._onChange = fn; }
|
|
|
|
}
|
|
|
|
|
2018-09-20 15:18:14 +01:00
|
|
|
export interface ValidatorFn { (control: AbstractControl): ValidationErrors|null; }
|
2016-06-27 12:27:23 -07:00
|
|
|
|
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-04-05 10:58:12 +01:00
|
|
|
* Provider which adds `MinLengthValidator` to `NG_VALIDATORS`.
|
2016-06-08 15:36:24 -07:00
|
|
|
*
|
2018-09-20 15:18:14 +01:00
|
|
|
* @usageNotes
|
|
|
|
* ### Example:
|
2016-06-08 15:36:24 -07:00
|
|
|
*
|
|
|
|
* {@example common/forms/ts/validators/validators.ts region='min'}
|
|
|
|
*/
|
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-04-05 10:58:12 +01:00
|
|
|
* A directive which installs the `MinLengthValidator` for any `formControlName`,
|
2016-06-10 17:28:19 -07:00
|
|
|
* `formControl`, or control with `ngModel` that also has a `minlength` attribute.
|
2016-06-08 15:36:24 -07:00
|
|
|
*
|
2018-09-08 17:53:53 +01:00
|
|
|
* @ngModule FormsModule
|
|
|
|
* @ngModule ReactiveFormsModule
|
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-06-18 16:38:33 -07:00
|
|
|
// TODO(issue/24571): remove '!'.
|
|
|
|
@Input() minlength !: string;
|
2016-08-06 08:53:41 +02:00
|
|
|
|
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-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
|
|
|
|
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-04-05 10:58:12 +01:00
|
|
|
* Provider which adds `MaxLengthValidator` to `NG_VALIDATORS`.
|
2016-06-08 15:36:24 -07:00
|
|
|
*
|
2018-09-20 15:18:14 +01:00
|
|
|
* @usageNotes
|
|
|
|
* ### Example:
|
2016-06-08 15:36:24 -07:00
|
|
|
*
|
|
|
|
* {@example common/forms/ts/validators/validators.ts region='max'}
|
|
|
|
*/
|
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-06-12 15:11:13 -05:00
|
|
|
* A directive which installs the `MaxLengthValidator` for any `formControlName`,
|
|
|
|
* `formControl`, or control with `ngModel` that also has a `maxlength` attribute.
|
2016-06-08 15:36:24 -07:00
|
|
|
*
|
2018-09-08 17:53:53 +01:00
|
|
|
* @ngModule FormsModule
|
|
|
|
* @ngModule ReactiveFormsModule
|
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-06-18 16:38:33 -07:00
|
|
|
// TODO(issue/24571): remove '!'.
|
|
|
|
@Input() maxlength !: string;
|
2016-08-06 08:53:41 +02:00
|
|
|
|
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-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
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
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
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A Directive that adds the `pattern` validator to any controls marked with the
|
2018-04-05 10:58:12 +01:00
|
|
|
* `pattern` attribute, via the `NG_VALIDATORS` binding. Uses attribute value
|
2016-06-08 15:36:24 -07:00
|
|
|
* as the regex to validate Control value against. Follows pattern attribute
|
|
|
|
* semantics; i.e. regex must match entire Control value.
|
|
|
|
*
|
2018-09-20 15:18:14 +01:00
|
|
|
* @usageNotes
|
2016-06-08 15:36:24 -07:00
|
|
|
* ### Example
|
|
|
|
*
|
|
|
|
* ```
|
2016-06-12 13:17:07 -07:00
|
|
|
* <input [name]="fullName" pattern="[a-zA-Z ]*" ngModel>
|
2016-06-08 15:36:24 -07:00
|
|
|
* ```
|
2018-04-05 22:31:44 +01:00
|
|
|
*
|
2018-09-08 17:53:53 +01:00
|
|
|
* @ngModule FormsModule
|
|
|
|
* @ngModule ReactiveFormsModule
|
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-06-18 16:38:33 -07:00
|
|
|
// TODO(issue/24571): remove '!'.
|
|
|
|
@Input() pattern !: string | RegExp;
|
2016-08-06 08:53:41 +02:00
|
|
|
|
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-09-20 15:18:14 +01:00
|
|
|
validate(control: AbstractControl): ValidationErrors|null { return this._validator(control); }
|
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
|
|
|
}
|