parent
0b665c0ece
commit
d2ad871279
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
import {AbstractControlDirective} from './abstract_control_directive';
|
import {AbstractControlDirective} from './abstract_control_directive';
|
||||||
import {ControlValueAccessor} from './control_value_accessor';
|
import {ControlValueAccessor} from './control_value_accessor';
|
||||||
import {AsyncValidatorFn, ValidatorFn} from './validators';
|
import {AsyncValidatorFn, Validator, ValidatorFn} from './validators';
|
||||||
|
|
||||||
function unimplemented(): any {
|
function unimplemented(): any {
|
||||||
throw new Error('unimplemented');
|
throw new Error('unimplemented');
|
||||||
|
@ -26,6 +26,10 @@ function unimplemented(): any {
|
||||||
export abstract class NgControl extends AbstractControlDirective {
|
export abstract class NgControl extends AbstractControlDirective {
|
||||||
name: string = null;
|
name: string = null;
|
||||||
valueAccessor: ControlValueAccessor = null;
|
valueAccessor: ControlValueAccessor = null;
|
||||||
|
/** @internal */
|
||||||
|
_rawValidators: Array<Validator|ValidatorFn> = [];
|
||||||
|
/** @internal */
|
||||||
|
_rawAsyncValidators: Array<Validator|ValidatorFn> = [];
|
||||||
|
|
||||||
get validator(): ValidatorFn { return <ValidatorFn>unimplemented(); }
|
get validator(): ValidatorFn { return <ValidatorFn>unimplemented(); }
|
||||||
get asyncValidator(): AsyncValidatorFn { return <AsyncValidatorFn>unimplemented(); }
|
get asyncValidator(): AsyncValidatorFn { return <AsyncValidatorFn>unimplemented(); }
|
||||||
|
|
|
@ -20,7 +20,7 @@ import {NgForm} from './ng_form';
|
||||||
import {NgModelGroup} from './ng_model_group';
|
import {NgModelGroup} from './ng_model_group';
|
||||||
import {composeAsyncValidators, composeValidators, controlPath, isPropertyUpdated, selectValueAccessor, setUpControl} from './shared';
|
import {composeAsyncValidators, composeValidators, controlPath, isPropertyUpdated, selectValueAccessor, setUpControl} from './shared';
|
||||||
import {TemplateDrivenErrors} from './template_driven_errors';
|
import {TemplateDrivenErrors} from './template_driven_errors';
|
||||||
import {AsyncValidatorFn, ValidatorFn} from './validators';
|
import {AsyncValidatorFn, Validator, ValidatorFn} from './validators';
|
||||||
|
|
||||||
export const formControlBinding: any = {
|
export const formControlBinding: any = {
|
||||||
provide: NgControl,
|
provide: NgControl,
|
||||||
|
@ -72,11 +72,13 @@ export class NgModel extends NgControl implements OnChanges,
|
||||||
@Output('ngModelChange') update = new EventEmitter();
|
@Output('ngModelChange') update = new EventEmitter();
|
||||||
|
|
||||||
constructor(@Optional() @Host() private _parent: ControlContainer,
|
constructor(@Optional() @Host() private _parent: ControlContainer,
|
||||||
@Optional() @Self() @Inject(NG_VALIDATORS) private _validators: any[],
|
@Optional() @Self() @Inject(NG_VALIDATORS) validators: Array<Validator|ValidatorFn>,
|
||||||
@Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) private _asyncValidators: any[],
|
@Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) asyncValidators: Array<Validator|AsyncValidatorFn>,
|
||||||
@Optional() @Self() @Inject(NG_VALUE_ACCESSOR)
|
@Optional() @Self() @Inject(NG_VALUE_ACCESSOR)
|
||||||
valueAccessors: ControlValueAccessor[]) {
|
valueAccessors: ControlValueAccessor[]) {
|
||||||
super();
|
super();
|
||||||
|
this._rawValidators = validators || [];
|
||||||
|
this._rawAsyncValidators = asyncValidators || [];
|
||||||
this.valueAccessor = selectValueAccessor(this, valueAccessors);
|
this.valueAccessor = selectValueAccessor(this, valueAccessors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,10 +105,10 @@ export class NgModel extends NgControl implements OnChanges,
|
||||||
|
|
||||||
get formDirective(): any { return this._parent ? this._parent.formDirective : null; }
|
get formDirective(): any { return this._parent ? this._parent.formDirective : null; }
|
||||||
|
|
||||||
get validator(): ValidatorFn { return composeValidators(this._validators); }
|
get validator(): ValidatorFn { return composeValidators(this._rawValidators); }
|
||||||
|
|
||||||
get asyncValidator(): AsyncValidatorFn {
|
get asyncValidator(): AsyncValidatorFn {
|
||||||
return composeAsyncValidators(this._asyncValidators);
|
return composeAsyncValidators(this._rawAsyncValidators);
|
||||||
}
|
}
|
||||||
|
|
||||||
viewToModelUpdate(newValue: any): void {
|
viewToModelUpdate(newValue: any): void {
|
||||||
|
|
|
@ -16,7 +16,7 @@ import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '../control_value_accessor
|
||||||
import {NgControl} from '../ng_control';
|
import {NgControl} from '../ng_control';
|
||||||
import {ReactiveErrors} from '../reactive_errors';
|
import {ReactiveErrors} from '../reactive_errors';
|
||||||
import {composeAsyncValidators, composeValidators, isPropertyUpdated, selectValueAccessor, setUpControl} from '../shared';
|
import {composeAsyncValidators, composeValidators, isPropertyUpdated, selectValueAccessor, setUpControl} from '../shared';
|
||||||
import {AsyncValidatorFn, ValidatorFn} from '../validators';
|
import {AsyncValidatorFn, Validator, ValidatorFn} from '../validators';
|
||||||
|
|
||||||
export const formControlBinding: any = {
|
export const formControlBinding: any = {
|
||||||
provide: NgControl,
|
provide: NgControl,
|
||||||
|
@ -84,13 +84,13 @@ export class FormControlDirective extends NgControl implements OnChanges {
|
||||||
@Input('disabled')
|
@Input('disabled')
|
||||||
set isDisabled(isDisabled: boolean) { ReactiveErrors.disabledAttrWarning(); }
|
set isDisabled(isDisabled: boolean) { ReactiveErrors.disabledAttrWarning(); }
|
||||||
|
|
||||||
constructor(@Optional() @Self() @Inject(NG_VALIDATORS) private _validators:
|
constructor(@Optional() @Self() @Inject(NG_VALIDATORS) validators: Array<Validator|ValidatorFn>,
|
||||||
/* Array<Validator|Function> */ any[],
|
@Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) asyncValidators: Array<Validator|AsyncValidatorFn>,
|
||||||
@Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) private _asyncValidators:
|
|
||||||
/* Array<Validator|Function> */ any[],
|
|
||||||
@Optional() @Self() @Inject(NG_VALUE_ACCESSOR)
|
@Optional() @Self() @Inject(NG_VALUE_ACCESSOR)
|
||||||
valueAccessors: ControlValueAccessor[]) {
|
valueAccessors: ControlValueAccessor[]) {
|
||||||
super();
|
super();
|
||||||
|
this._rawValidators = validators || [];
|
||||||
|
this._rawAsyncValidators = asyncValidators || [];
|
||||||
this.valueAccessor = selectValueAccessor(this, valueAccessors);
|
this.valueAccessor = selectValueAccessor(this, valueAccessors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,10 +108,10 @@ export class FormControlDirective extends NgControl implements OnChanges {
|
||||||
|
|
||||||
get path(): string[] { return []; }
|
get path(): string[] { return []; }
|
||||||
|
|
||||||
get validator(): ValidatorFn { return composeValidators(this._validators); }
|
get validator(): ValidatorFn { return composeValidators(this._rawValidators); }
|
||||||
|
|
||||||
get asyncValidator(): AsyncValidatorFn {
|
get asyncValidator(): AsyncValidatorFn {
|
||||||
return composeAsyncValidators(this._asyncValidators);
|
return composeAsyncValidators(this._rawAsyncValidators);
|
||||||
}
|
}
|
||||||
|
|
||||||
get control(): FormControl { return this.form; }
|
get control(): FormControl { return this.form; }
|
||||||
|
|
|
@ -17,7 +17,7 @@ import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '../control_value_accessor
|
||||||
import {NgControl} from '../ng_control';
|
import {NgControl} from '../ng_control';
|
||||||
import {ReactiveErrors} from '../reactive_errors';
|
import {ReactiveErrors} from '../reactive_errors';
|
||||||
import {composeAsyncValidators, composeValidators, controlPath, isPropertyUpdated, selectValueAccessor} from '../shared';
|
import {composeAsyncValidators, composeValidators, controlPath, isPropertyUpdated, selectValueAccessor} from '../shared';
|
||||||
import {AsyncValidatorFn, ValidatorFn} from '../validators';
|
import {AsyncValidatorFn, Validator, ValidatorFn} from '../validators';
|
||||||
|
|
||||||
import {FormGroupDirective} from './form_group_directive';
|
import {FormGroupDirective} from './form_group_directive';
|
||||||
import {FormArrayName, FormGroupName} from './form_group_name';
|
import {FormArrayName, FormGroupName} from './form_group_name';
|
||||||
|
@ -110,12 +110,13 @@ export class FormControlName extends NgControl implements OnChanges, OnDestroy {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Optional() @Host() @SkipSelf() private _parent: ControlContainer,
|
@Optional() @Host() @SkipSelf() private _parent: ControlContainer,
|
||||||
@Optional() @Self() @Inject(NG_VALIDATORS) private _validators:
|
@Optional() @Self() @Inject(NG_VALIDATORS) validators: Array<Validator|ValidatorFn>,
|
||||||
/* Array<Validator|Function> */ any[],
|
@Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) asyncValidators:
|
||||||
@Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) private _asyncValidators:
|
Array<Validator|AsyncValidatorFn>,
|
||||||
/* Array<Validator|Function> */ any[],
|
|
||||||
@Optional() @Self() @Inject(NG_VALUE_ACCESSOR) valueAccessors: ControlValueAccessor[]) {
|
@Optional() @Self() @Inject(NG_VALUE_ACCESSOR) valueAccessors: ControlValueAccessor[]) {
|
||||||
super();
|
super();
|
||||||
|
this._rawValidators = validators || [];
|
||||||
|
this._rawAsyncValidators = asyncValidators || [];
|
||||||
this.valueAccessor = selectValueAccessor(this, valueAccessors);
|
this.valueAccessor = selectValueAccessor(this, valueAccessors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,9 +148,11 @@ export class FormControlName extends NgControl implements OnChanges, OnDestroy {
|
||||||
|
|
||||||
get formDirective(): any { return this._parent ? this._parent.formDirective : null; }
|
get formDirective(): any { return this._parent ? this._parent.formDirective : null; }
|
||||||
|
|
||||||
get validator(): ValidatorFn { return composeValidators(this._validators); }
|
get validator(): ValidatorFn { return composeValidators(this._rawValidators); }
|
||||||
|
|
||||||
get asyncValidator(): AsyncValidatorFn { return composeAsyncValidators(this._asyncValidators); }
|
get asyncValidator(): AsyncValidatorFn {
|
||||||
|
return composeAsyncValidators(this._rawAsyncValidators);
|
||||||
|
}
|
||||||
|
|
||||||
get control(): FormControl { return this.formDirective.getControl(this); }
|
get control(): FormControl { return this.formDirective.getControl(this); }
|
||||||
|
|
||||||
|
|
|
@ -124,7 +124,6 @@ export class FormGroupDirective extends ControlContainer implements Form,
|
||||||
|
|
||||||
var async = composeAsyncValidators(this._asyncValidators);
|
var async = composeAsyncValidators(this._asyncValidators);
|
||||||
this.form.asyncValidator = Validators.composeAsync([this.form.asyncValidator, async]);
|
this.form.asyncValidator = Validators.composeAsync([this.form.asyncValidator, async]);
|
||||||
this.form.updateValueAndValidity({onlySelf: true, emitEvent: false});
|
|
||||||
this._updateDomValue(changes);
|
this._updateDomValue(changes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -189,6 +188,7 @@ export class FormGroupDirective extends ControlContainer implements Form,
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_updateDomValue(changes: SimpleChanges) {
|
_updateDomValue(changes: SimpleChanges) {
|
||||||
const oldForm = changes['form'].previousValue;
|
const oldForm = changes['form'].previousValue;
|
||||||
|
|
||||||
this.directives.forEach(dir => {
|
this.directives.forEach(dir => {
|
||||||
const newCtrl: any = this.form.get(dir.path);
|
const newCtrl: any = this.form.get(dir.path);
|
||||||
const oldCtrl = oldForm.get(dir.path);
|
const oldCtrl = oldForm.get(dir.path);
|
||||||
|
@ -197,6 +197,8 @@ export class FormGroupDirective extends ControlContainer implements Form,
|
||||||
if (newCtrl) setUpControl(newCtrl, dir);
|
if (newCtrl) setUpControl(newCtrl, dir);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.form._updateTreeValidity({emitEvent: false});
|
||||||
}
|
}
|
||||||
|
|
||||||
private _checkFormPresent() {
|
private _checkFormPresent() {
|
||||||
|
|
|
@ -25,7 +25,7 @@ import {RadioControlValueAccessor} from './radio_control_value_accessor';
|
||||||
import {FormArrayName} from './reactive_directives/form_group_name';
|
import {FormArrayName} from './reactive_directives/form_group_name';
|
||||||
import {SelectControlValueAccessor} from './select_control_value_accessor';
|
import {SelectControlValueAccessor} from './select_control_value_accessor';
|
||||||
import {SelectMultipleControlValueAccessor} from './select_multiple_control_value_accessor';
|
import {SelectMultipleControlValueAccessor} from './select_multiple_control_value_accessor';
|
||||||
import {AsyncValidatorFn, ValidatorFn} from './validators';
|
import {AsyncValidatorFn, Validator, ValidatorFn} from './validators';
|
||||||
|
|
||||||
|
|
||||||
export function controlPath(name: string, parent: ControlContainer): string[] {
|
export function controlPath(name: string, parent: ControlContainer): string[] {
|
||||||
|
@ -49,6 +49,9 @@ export function setUpControl(control: FormControl, dir: NgControl): void {
|
||||||
control.setValue(newValue, {emitModelToViewChange: false});
|
control.setValue(newValue, {emitModelToViewChange: false});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// touched
|
||||||
|
dir.valueAccessor.registerOnTouched(() => control.markAsTouched());
|
||||||
|
|
||||||
control.registerOnChange((newValue: any, emitModelEvent: boolean) => {
|
control.registerOnChange((newValue: any, emitModelEvent: boolean) => {
|
||||||
// control -> view
|
// control -> view
|
||||||
dir.valueAccessor.writeValue(newValue);
|
dir.valueAccessor.writeValue(newValue);
|
||||||
|
@ -62,13 +65,23 @@ export function setUpControl(control: FormControl, dir: NgControl): void {
|
||||||
(isDisabled: boolean) => { dir.valueAccessor.setDisabledState(isDisabled); });
|
(isDisabled: boolean) => { dir.valueAccessor.setDisabledState(isDisabled); });
|
||||||
}
|
}
|
||||||
|
|
||||||
// touched
|
// re-run validation when validator binding changes, e.g. minlength=3 -> minlength=4
|
||||||
dir.valueAccessor.registerOnTouched(() => control.markAsTouched());
|
dir._rawValidators.forEach((validator: Validator | ValidatorFn) => {
|
||||||
|
if ((<Validator>validator).registerOnChange)
|
||||||
|
(<Validator>validator).registerOnChange(() => control.updateValueAndValidity());
|
||||||
|
});
|
||||||
|
|
||||||
|
dir._rawAsyncValidators.forEach((validator: Validator | ValidatorFn) => {
|
||||||
|
if ((<Validator>validator).registerOnChange)
|
||||||
|
(<Validator>validator).registerOnChange(() => control.updateValueAndValidity());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function cleanUpControl(control: FormControl, dir: NgControl) {
|
export function cleanUpControl(control: FormControl, dir: NgControl) {
|
||||||
dir.valueAccessor.registerOnChange(() => _noControlError(dir));
|
dir.valueAccessor.registerOnChange(() => _noControlError(dir));
|
||||||
dir.valueAccessor.registerOnTouched(() => _noControlError(dir));
|
dir.valueAccessor.registerOnTouched(() => _noControlError(dir));
|
||||||
|
dir._rawValidators.forEach((validator: Validator) => validator.registerOnChange(null));
|
||||||
|
dir._rawAsyncValidators.forEach((validator: Validator) => validator.registerOnChange(null));
|
||||||
if (control) control._clearChangeFns();
|
if (control) control._clearChangeFns();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Attribute, Directive, HostBinding, Input, OnChanges, SimpleChanges, forwardRef} from '@angular/core';
|
import {Directive, Input, OnChanges, SimpleChanges, forwardRef} from '@angular/core';
|
||||||
|
|
||||||
import {isPresent} from '../facade/lang';
|
import {isPresent} from '../facade/lang';
|
||||||
import {AbstractControl} from '../model';
|
import {AbstractControl} from '../model';
|
||||||
|
@ -33,7 +33,10 @@ import {NG_VALIDATORS, Validators} from '../validators';
|
||||||
*
|
*
|
||||||
* @stable
|
* @stable
|
||||||
*/
|
*/
|
||||||
export interface Validator { validate(c: AbstractControl): {[key: string]: any}; }
|
export interface Validator {
|
||||||
|
validate(c: AbstractControl): {[key: string]: any};
|
||||||
|
registerOnChange?(fn: () => void): void;
|
||||||
|
}
|
||||||
|
|
||||||
export const REQUIRED_VALIDATOR: any = {
|
export const REQUIRED_VALIDATOR: any = {
|
||||||
provide: NG_VALIDATORS,
|
provide: NG_VALIDATORS,
|
||||||
|
@ -60,15 +63,21 @@ export const REQUIRED_VALIDATOR: any = {
|
||||||
})
|
})
|
||||||
export class RequiredValidator implements Validator {
|
export class RequiredValidator implements Validator {
|
||||||
private _required: boolean;
|
private _required: boolean;
|
||||||
|
private _onChange: () => void;
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
get required(): boolean { return this._required; }
|
get required(): boolean { return this._required; }
|
||||||
|
|
||||||
set required(value: boolean) { this._required = isPresent(value) && `${value}` !== 'false'; }
|
set required(value: boolean) {
|
||||||
|
this._required = isPresent(value) && `${value}` !== 'false';
|
||||||
|
if (this._onChange) this._onChange();
|
||||||
|
}
|
||||||
|
|
||||||
validate(c: AbstractControl): {[key: string]: any} {
|
validate(c: AbstractControl): {[key: string]: any} {
|
||||||
return this.required ? Validators.required(c) : null;
|
return this.required ? Validators.required(c) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
registerOnChange(fn: () => void) { this._onChange = fn; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -110,6 +119,7 @@ export const MIN_LENGTH_VALIDATOR: any = {
|
||||||
export class MinLengthValidator implements Validator,
|
export class MinLengthValidator implements Validator,
|
||||||
OnChanges {
|
OnChanges {
|
||||||
private _validator: ValidatorFn;
|
private _validator: ValidatorFn;
|
||||||
|
private _onChange: () => void;
|
||||||
|
|
||||||
@Input() minlength: string;
|
@Input() minlength: string;
|
||||||
|
|
||||||
|
@ -118,15 +128,17 @@ export class MinLengthValidator implements Validator,
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges(changes: SimpleChanges) {
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
const minlengthChange = changes['minlength'];
|
if (changes['minlength']) {
|
||||||
if (minlengthChange) {
|
|
||||||
this._createValidator();
|
this._createValidator();
|
||||||
|
if (this._onChange) this._onChange();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
validate(c: AbstractControl): {[key: string]: any} {
|
validate(c: AbstractControl): {[key: string]: any} {
|
||||||
return isPresent(this.minlength) ? this._validator(c) : null;
|
return isPresent(this.minlength) ? this._validator(c) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
registerOnChange(fn: () => void) { this._onChange = fn; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -157,6 +169,7 @@ export const MAX_LENGTH_VALIDATOR: any = {
|
||||||
export class MaxLengthValidator implements Validator,
|
export class MaxLengthValidator implements Validator,
|
||||||
OnChanges {
|
OnChanges {
|
||||||
private _validator: ValidatorFn;
|
private _validator: ValidatorFn;
|
||||||
|
private _onChange: () => void;
|
||||||
|
|
||||||
@Input() maxlength: string;
|
@Input() maxlength: string;
|
||||||
|
|
||||||
|
@ -165,15 +178,17 @@ export class MaxLengthValidator implements Validator,
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges(changes: SimpleChanges) {
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
const maxlengthChange = changes['maxlength'];
|
if (changes['maxlength']) {
|
||||||
if (maxlengthChange) {
|
|
||||||
this._createValidator();
|
this._createValidator();
|
||||||
|
if (this._onChange) this._onChange();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
validate(c: AbstractControl): {[key: string]: any} {
|
validate(c: AbstractControl): {[key: string]: any} {
|
||||||
return isPresent(this.maxlength) ? this._validator(c) : null;
|
return isPresent(this.maxlength) ? this._validator(c) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
registerOnChange(fn: () => void) { this._onChange = fn; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -205,19 +220,22 @@ export const PATTERN_VALIDATOR: any = {
|
||||||
export class PatternValidator implements Validator,
|
export class PatternValidator implements Validator,
|
||||||
OnChanges {
|
OnChanges {
|
||||||
private _validator: ValidatorFn;
|
private _validator: ValidatorFn;
|
||||||
|
private _onChange: () => void;
|
||||||
|
|
||||||
@Input() pattern: string;
|
@Input() pattern: string;
|
||||||
|
|
||||||
private _createValidator() { this._validator = Validators.pattern(this.pattern); }
|
private _createValidator() { this._validator = Validators.pattern(this.pattern); }
|
||||||
|
|
||||||
ngOnChanges(changes: SimpleChanges) {
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
const patternChange = changes['pattern'];
|
if (changes['pattern']) {
|
||||||
if (patternChange) {
|
|
||||||
this._createValidator();
|
this._createValidator();
|
||||||
|
if (this._onChange) this._onChange();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
validate(c: AbstractControl): {[key: string]: any} {
|
validate(c: AbstractControl): {[key: string]: any} {
|
||||||
return isPresent(this.pattern) ? this._validator(c) : null;
|
return isPresent(this.pattern) ? this._validator(c) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
registerOnChange(fn: () => void) { this._onChange = fn; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -253,6 +253,12 @@ export abstract class AbstractControl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
_updateTreeValidity({emitEvent}: {emitEvent?: boolean} = {emitEvent: true}) {
|
||||||
|
this._forEachChild((ctrl: AbstractControl) => ctrl._updateTreeValidity({emitEvent}));
|
||||||
|
this.updateValueAndValidity({onlySelf: true, emitEvent});
|
||||||
|
}
|
||||||
|
|
||||||
private _runValidator(): {[key: string]: any} {
|
private _runValidator(): {[key: string]: any} {
|
||||||
return isPresent(this.validator) ? this.validator(this) : null;
|
return isPresent(this.validator) ? this.validator(this) : null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -809,5 +809,39 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('updateTreeValidity()', () => {
|
||||||
|
let c: FormControl, c2: FormControl, c3: FormControl;
|
||||||
|
let nested: FormGroup, form: FormGroup;
|
||||||
|
let logger: string[];
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
c = new FormControl('one');
|
||||||
|
c2 = new FormControl('two');
|
||||||
|
c3 = new FormControl('three');
|
||||||
|
nested = new FormGroup({one: c, two: c2});
|
||||||
|
form = new FormGroup({nested: nested, three: c3});
|
||||||
|
logger = [];
|
||||||
|
|
||||||
|
c.statusChanges.subscribe(() => logger.push('one'));
|
||||||
|
c2.statusChanges.subscribe(() => logger.push('two'));
|
||||||
|
c3.statusChanges.subscribe(() => logger.push('three'));
|
||||||
|
nested.statusChanges.subscribe(() => logger.push('nested'));
|
||||||
|
form.statusChanges.subscribe(() => logger.push('form'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update tree validity', () => {
|
||||||
|
form._updateTreeValidity();
|
||||||
|
expect(logger).toEqual(['one', 'two', 'nested', 'three', 'form']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not emit events when turned off', () => {
|
||||||
|
form._updateTreeValidity({emitEvent: false});
|
||||||
|
expect(logger).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,6 +160,30 @@ export function main() {
|
||||||
expect(inputs[0].nativeElement.value).toEqual('Bess');
|
expect(inputs[0].nativeElement.value).toEqual('Bess');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should pick up dir validators from form controls', () => {
|
||||||
|
const fixture = TestBed.createComponent(LoginIsEmptyWrapper);
|
||||||
|
const form = new FormGroup({
|
||||||
|
'login': new FormControl(''),
|
||||||
|
'min': new FormControl(''),
|
||||||
|
'max': new FormControl(''),
|
||||||
|
'pattern': new FormControl('')
|
||||||
|
});
|
||||||
|
fixture.debugElement.componentInstance.form = form;
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(form.get('login').errors).toEqual({required: true});
|
||||||
|
|
||||||
|
const newForm = new FormGroup({
|
||||||
|
'login': new FormControl(''),
|
||||||
|
'min': new FormControl(''),
|
||||||
|
'max': new FormControl(''),
|
||||||
|
'pattern': new FormControl('')
|
||||||
|
});
|
||||||
|
fixture.debugElement.componentInstance.form = newForm;
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(newForm.get('login').errors).toEqual({required: true});
|
||||||
|
});
|
||||||
|
|
||||||
it('should pick up dir validators from nested form groups', () => {
|
it('should pick up dir validators from nested form groups', () => {
|
||||||
const fixture = TestBed.createComponent(NestedFormGroupComp);
|
const fixture = TestBed.createComponent(NestedFormGroupComp);
|
||||||
const form = new FormGroup({
|
const form = new FormGroup({
|
||||||
|
@ -1024,7 +1048,7 @@ export function main() {
|
||||||
expect(form.valid).toEqual(true);
|
expect(form.valid).toEqual(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('changes on binded properties should change the validation state of the form', () => {
|
it('changes on bound properties should change the validation state of the form', () => {
|
||||||
const fixture = TestBed.createComponent(ValidationBindingsForm);
|
const fixture = TestBed.createComponent(ValidationBindingsForm);
|
||||||
const form = new FormGroup({
|
const form = new FormGroup({
|
||||||
'login': new FormControl(''),
|
'login': new FormControl(''),
|
||||||
|
@ -1087,11 +1111,6 @@ export function main() {
|
||||||
fixture.debugElement.componentInstance.pattern = null;
|
fixture.debugElement.componentInstance.pattern = null;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
dispatchEvent(required.nativeElement, 'input');
|
|
||||||
dispatchEvent(minLength.nativeElement, 'input');
|
|
||||||
dispatchEvent(maxLength.nativeElement, 'input');
|
|
||||||
dispatchEvent(pattern.nativeElement, 'input');
|
|
||||||
|
|
||||||
expect(form.hasError('required', ['login'])).toEqual(false);
|
expect(form.hasError('required', ['login'])).toEqual(false);
|
||||||
expect(form.hasError('minlength', ['min'])).toEqual(false);
|
expect(form.hasError('minlength', ['min'])).toEqual(false);
|
||||||
expect(form.hasError('maxlength', ['max'])).toEqual(false);
|
expect(form.hasError('maxlength', ['max'])).toEqual(false);
|
||||||
|
@ -1104,6 +1123,43 @@ export function main() {
|
||||||
expect(required.nativeElement.getAttribute('pattern')).toEqual(null);
|
expect(required.nativeElement.getAttribute('pattern')).toEqual(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should support rebound controls with rebound validators', () => {
|
||||||
|
const fixture = TestBed.createComponent(ValidationBindingsForm);
|
||||||
|
const form = new FormGroup({
|
||||||
|
'login': new FormControl(''),
|
||||||
|
'min': new FormControl(''),
|
||||||
|
'max': new FormControl(''),
|
||||||
|
'pattern': new FormControl('')
|
||||||
|
});
|
||||||
|
fixture.debugElement.componentInstance.form = form;
|
||||||
|
fixture.debugElement.componentInstance.required = true;
|
||||||
|
fixture.debugElement.componentInstance.minLen = 3;
|
||||||
|
fixture.debugElement.componentInstance.maxLen = 3;
|
||||||
|
fixture.debugElement.componentInstance.pattern = '.{3,}';
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const newForm = new FormGroup({
|
||||||
|
'login': new FormControl(''),
|
||||||
|
'min': new FormControl(''),
|
||||||
|
'max': new FormControl(''),
|
||||||
|
'pattern': new FormControl('')
|
||||||
|
});
|
||||||
|
fixture.debugElement.componentInstance.form = newForm;
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
fixture.debugElement.componentInstance.required = false;
|
||||||
|
fixture.debugElement.componentInstance.minLen = null;
|
||||||
|
fixture.debugElement.componentInstance.maxLen = null;
|
||||||
|
fixture.debugElement.componentInstance.pattern = null;
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(newForm.hasError('required', ['login'])).toEqual(false);
|
||||||
|
expect(newForm.hasError('minlength', ['min'])).toEqual(false);
|
||||||
|
expect(newForm.hasError('maxlength', ['max'])).toEqual(false);
|
||||||
|
expect(newForm.hasError('pattern', ['pattern'])).toEqual(false);
|
||||||
|
expect(newForm.valid).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
it('should use async validators defined in the html', fakeAsync(() => {
|
it('should use async validators defined in the html', fakeAsync(() => {
|
||||||
const fixture = TestBed.createComponent(UniqLoginWrapper);
|
const fixture = TestBed.createComponent(UniqLoginWrapper);
|
||||||
const form = new FormGroup({'login': new FormControl('')});
|
const form = new FormGroup({'login': new FormControl('')});
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
import {NgFor, NgIf} from '@angular/common';
|
import {NgFor, NgIf} from '@angular/common';
|
||||||
import {Component, Input} from '@angular/core';
|
import {Component, Input} from '@angular/core';
|
||||||
import {TestBed, async, fakeAsync, tick} from '@angular/core/testing';
|
import {TestBed, async, fakeAsync, tick} from '@angular/core/testing';
|
||||||
import {beforeEach, ddescribe, describe, expect, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
|
|
||||||
import {ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR, NgForm} from '@angular/forms';
|
import {ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR, NgForm} from '@angular/forms';
|
||||||
import {By} from '@angular/platform-browser/src/dom/debug/by';
|
import {By} from '@angular/platform-browser/src/dom/debug/by';
|
||||||
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
|
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
|
||||||
|
@ -25,7 +24,8 @@ export function main() {
|
||||||
declarations: [
|
declarations: [
|
||||||
StandaloneNgModel, NgModelForm, NgModelGroupForm, NgModelValidBinding, NgModelNgIfForm,
|
StandaloneNgModel, NgModelForm, NgModelGroupForm, NgModelValidBinding, NgModelNgIfForm,
|
||||||
NgModelRadioForm, NgModelSelectForm, NgNoFormComp, InvalidNgModelNoName,
|
NgModelRadioForm, NgModelSelectForm, NgNoFormComp, InvalidNgModelNoName,
|
||||||
NgModelOptionsStandalone, NgModelCustomComp, NgModelCustomWrapper
|
NgModelOptionsStandalone, NgModelCustomComp, NgModelCustomWrapper,
|
||||||
|
NgModelValidationBindings
|
||||||
],
|
],
|
||||||
imports: [FormsModule]
|
imports: [FormsModule]
|
||||||
});
|
});
|
||||||
|
@ -574,6 +574,125 @@ export function main() {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('validation directives', () => {
|
||||||
|
|
||||||
|
it('should support dir validators using bindings', fakeAsync(() => {
|
||||||
|
const fixture = TestBed.createComponent(NgModelValidationBindings);
|
||||||
|
fixture.debugElement.componentInstance.required = true;
|
||||||
|
fixture.debugElement.componentInstance.minLen = 3;
|
||||||
|
fixture.debugElement.componentInstance.maxLen = 3;
|
||||||
|
fixture.debugElement.componentInstance.pattern = '.{3,}';
|
||||||
|
fixture.detectChanges();
|
||||||
|
tick();
|
||||||
|
|
||||||
|
const required = fixture.debugElement.query(By.css('[name=required]'));
|
||||||
|
const minLength = fixture.debugElement.query(By.css('[name=minlength]'));
|
||||||
|
const maxLength = fixture.debugElement.query(By.css('[name=maxlength]'));
|
||||||
|
const pattern = fixture.debugElement.query(By.css('[name=pattern]'));
|
||||||
|
|
||||||
|
required.nativeElement.value = '';
|
||||||
|
minLength.nativeElement.value = '1';
|
||||||
|
maxLength.nativeElement.value = '1234';
|
||||||
|
pattern.nativeElement.value = '12';
|
||||||
|
|
||||||
|
dispatchEvent(required.nativeElement, 'input');
|
||||||
|
dispatchEvent(minLength.nativeElement, 'input');
|
||||||
|
dispatchEvent(maxLength.nativeElement, 'input');
|
||||||
|
dispatchEvent(pattern.nativeElement, 'input');
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const form = fixture.debugElement.children[0].injector.get(NgForm);
|
||||||
|
expect(form.control.hasError('required', ['required'])).toEqual(true);
|
||||||
|
expect(form.control.hasError('minlength', ['minlength'])).toEqual(true);
|
||||||
|
expect(form.control.hasError('maxlength', ['maxlength'])).toEqual(true);
|
||||||
|
expect(form.control.hasError('pattern', ['pattern'])).toEqual(true);
|
||||||
|
|
||||||
|
required.nativeElement.value = '1';
|
||||||
|
minLength.nativeElement.value = '123';
|
||||||
|
maxLength.nativeElement.value = '123';
|
||||||
|
pattern.nativeElement.value = '123';
|
||||||
|
|
||||||
|
dispatchEvent(required.nativeElement, 'input');
|
||||||
|
dispatchEvent(minLength.nativeElement, 'input');
|
||||||
|
dispatchEvent(maxLength.nativeElement, 'input');
|
||||||
|
dispatchEvent(pattern.nativeElement, 'input');
|
||||||
|
|
||||||
|
expect(form.valid).toEqual(true);
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('changes on bound properties should change the validation state of the form',
|
||||||
|
fakeAsync(() => {
|
||||||
|
const fixture = TestBed.createComponent(NgModelValidationBindings);
|
||||||
|
fixture.detectChanges();
|
||||||
|
tick();
|
||||||
|
|
||||||
|
const required = fixture.debugElement.query(By.css('[name=required]'));
|
||||||
|
const minLength = fixture.debugElement.query(By.css('[name=minlength]'));
|
||||||
|
const maxLength = fixture.debugElement.query(By.css('[name=maxlength]'));
|
||||||
|
const pattern = fixture.debugElement.query(By.css('[name=pattern]'));
|
||||||
|
|
||||||
|
required.nativeElement.value = '';
|
||||||
|
minLength.nativeElement.value = '1';
|
||||||
|
maxLength.nativeElement.value = '1234';
|
||||||
|
pattern.nativeElement.value = '12';
|
||||||
|
|
||||||
|
dispatchEvent(required.nativeElement, 'input');
|
||||||
|
dispatchEvent(minLength.nativeElement, 'input');
|
||||||
|
dispatchEvent(maxLength.nativeElement, 'input');
|
||||||
|
dispatchEvent(pattern.nativeElement, 'input');
|
||||||
|
|
||||||
|
const form = fixture.debugElement.children[0].injector.get(NgForm);
|
||||||
|
expect(form.control.hasError('required', ['required'])).toEqual(false);
|
||||||
|
expect(form.control.hasError('minlength', ['minlength'])).toEqual(false);
|
||||||
|
expect(form.control.hasError('maxlength', ['maxlength'])).toEqual(false);
|
||||||
|
expect(form.control.hasError('pattern', ['pattern'])).toEqual(false);
|
||||||
|
expect(form.valid).toEqual(true);
|
||||||
|
|
||||||
|
fixture.debugElement.componentInstance.required = true;
|
||||||
|
fixture.debugElement.componentInstance.minLen = 3;
|
||||||
|
fixture.debugElement.componentInstance.maxLen = 3;
|
||||||
|
fixture.debugElement.componentInstance.pattern = '.{3,}';
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
dispatchEvent(required.nativeElement, 'input');
|
||||||
|
dispatchEvent(minLength.nativeElement, 'input');
|
||||||
|
dispatchEvent(maxLength.nativeElement, 'input');
|
||||||
|
dispatchEvent(pattern.nativeElement, 'input');
|
||||||
|
|
||||||
|
expect(form.control.hasError('required', ['required'])).toEqual(true);
|
||||||
|
expect(form.control.hasError('minlength', ['minlength'])).toEqual(true);
|
||||||
|
expect(form.control.hasError('maxlength', ['maxlength'])).toEqual(true);
|
||||||
|
expect(form.control.hasError('pattern', ['pattern'])).toEqual(true);
|
||||||
|
expect(form.valid).toEqual(false);
|
||||||
|
|
||||||
|
expect(required.nativeElement.getAttribute('required')).toEqual('');
|
||||||
|
expect(fixture.debugElement.componentInstance.minLen.toString())
|
||||||
|
.toEqual(minLength.nativeElement.getAttribute('minlength'));
|
||||||
|
expect(fixture.debugElement.componentInstance.maxLen.toString())
|
||||||
|
.toEqual(maxLength.nativeElement.getAttribute('maxlength'));
|
||||||
|
expect(fixture.debugElement.componentInstance.pattern.toString())
|
||||||
|
.toEqual(pattern.nativeElement.getAttribute('pattern'));
|
||||||
|
|
||||||
|
fixture.debugElement.componentInstance.required = false;
|
||||||
|
fixture.debugElement.componentInstance.minLen = null;
|
||||||
|
fixture.debugElement.componentInstance.maxLen = null;
|
||||||
|
fixture.debugElement.componentInstance.pattern = null;
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(form.control.hasError('required', ['required'])).toEqual(false);
|
||||||
|
expect(form.control.hasError('minlength', ['minlength'])).toEqual(false);
|
||||||
|
expect(form.control.hasError('maxlength', ['maxlength'])).toEqual(false);
|
||||||
|
expect(form.control.hasError('pattern', ['pattern'])).toEqual(false);
|
||||||
|
expect(form.valid).toEqual(true);
|
||||||
|
|
||||||
|
expect(required.nativeElement.getAttribute('required')).toEqual(null);
|
||||||
|
expect(required.nativeElement.getAttribute('minlength')).toEqual(null);
|
||||||
|
expect(required.nativeElement.getAttribute('maxlength')).toEqual(null);
|
||||||
|
expect(required.nativeElement.getAttribute('pattern')).toEqual(null);
|
||||||
|
}));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
describe('ngModel corner cases', () => {
|
describe('ngModel corner cases', () => {
|
||||||
it('should update the view when the model is set back to what used to be in the view',
|
it('should update the view when the model is set back to what used to be in the view',
|
||||||
fakeAsync(() => {
|
fakeAsync(() => {
|
||||||
|
@ -791,6 +910,24 @@ class NgModelCustomWrapper {
|
||||||
isDisabled = false;
|
isDisabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ng-model-validation-bindings',
|
||||||
|
template: `
|
||||||
|
<form>
|
||||||
|
<input name="required" ngModel [required]="required">
|
||||||
|
<input name="minlength" ngModel [minlength]="minLen">
|
||||||
|
<input name="maxlength" ngModel [maxlength]="maxLen">
|
||||||
|
<input name="pattern" ngModel [pattern]="pattern">
|
||||||
|
</form>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
class NgModelValidationBindings {
|
||||||
|
required: boolean;
|
||||||
|
minLen: number;
|
||||||
|
maxLen: number;
|
||||||
|
pattern: string;
|
||||||
|
}
|
||||||
|
|
||||||
function sortedClassList(el: HTMLElement) {
|
function sortedClassList(el: HTMLElement) {
|
||||||
var l = getDOM().classList(el);
|
var l = getDOM().classList(el);
|
||||||
ListWrapper.sort(l);
|
ListWrapper.sort(l);
|
||||||
|
|
|
@ -229,7 +229,7 @@ export declare class FormControlDirective extends NgControl implements OnChanges
|
||||||
update: EventEmitter<{}>;
|
update: EventEmitter<{}>;
|
||||||
validator: ValidatorFn;
|
validator: ValidatorFn;
|
||||||
viewModel: any;
|
viewModel: any;
|
||||||
constructor(_validators: any[], _asyncValidators: any[], valueAccessors: ControlValueAccessor[]);
|
constructor(validators: Array<Validator | ValidatorFn>, asyncValidators: Array<Validator | AsyncValidatorFn>, valueAccessors: ControlValueAccessor[]);
|
||||||
ngOnChanges(changes: SimpleChanges): void;
|
ngOnChanges(changes: SimpleChanges): void;
|
||||||
viewToModelUpdate(newValue: any): void;
|
viewToModelUpdate(newValue: any): void;
|
||||||
}
|
}
|
||||||
|
@ -245,7 +245,7 @@ export declare class FormControlName extends NgControl implements OnChanges, OnD
|
||||||
path: string[];
|
path: string[];
|
||||||
update: EventEmitter<{}>;
|
update: EventEmitter<{}>;
|
||||||
validator: ValidatorFn;
|
validator: ValidatorFn;
|
||||||
constructor(_parent: ControlContainer, _validators: any[], _asyncValidators: any[], valueAccessors: ControlValueAccessor[]);
|
constructor(_parent: ControlContainer, validators: Array<Validator | ValidatorFn>, asyncValidators: Array<Validator | AsyncValidatorFn>, valueAccessors: ControlValueAccessor[]);
|
||||||
ngOnChanges(changes: SimpleChanges): void;
|
ngOnChanges(changes: SimpleChanges): void;
|
||||||
ngOnDestroy(): void;
|
ngOnDestroy(): void;
|
||||||
viewToModelUpdate(newValue: any): void;
|
viewToModelUpdate(newValue: any): void;
|
||||||
|
@ -319,6 +319,7 @@ export declare class FormsModule {
|
||||||
export declare class MaxLengthValidator implements Validator, OnChanges {
|
export declare class MaxLengthValidator implements Validator, OnChanges {
|
||||||
maxlength: string;
|
maxlength: string;
|
||||||
ngOnChanges(changes: SimpleChanges): void;
|
ngOnChanges(changes: SimpleChanges): void;
|
||||||
|
registerOnChange(fn: () => void): void;
|
||||||
validate(c: AbstractControl): {
|
validate(c: AbstractControl): {
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
};
|
};
|
||||||
|
@ -328,6 +329,7 @@ export declare class MaxLengthValidator implements Validator, OnChanges {
|
||||||
export declare class MinLengthValidator implements Validator, OnChanges {
|
export declare class MinLengthValidator implements Validator, OnChanges {
|
||||||
minlength: string;
|
minlength: string;
|
||||||
ngOnChanges(changes: SimpleChanges): void;
|
ngOnChanges(changes: SimpleChanges): void;
|
||||||
|
registerOnChange(fn: () => void): void;
|
||||||
validate(c: AbstractControl): {
|
validate(c: AbstractControl): {
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
};
|
};
|
||||||
|
@ -404,7 +406,7 @@ export declare class NgModel extends NgControl implements OnChanges, OnDestroy {
|
||||||
update: EventEmitter<{}>;
|
update: EventEmitter<{}>;
|
||||||
validator: ValidatorFn;
|
validator: ValidatorFn;
|
||||||
viewModel: any;
|
viewModel: any;
|
||||||
constructor(_parent: ControlContainer, _validators: any[], _asyncValidators: any[], valueAccessors: ControlValueAccessor[]);
|
constructor(_parent: ControlContainer, validators: Array<Validator | ValidatorFn>, asyncValidators: Array<Validator | AsyncValidatorFn>, valueAccessors: ControlValueAccessor[]);
|
||||||
ngOnChanges(changes: SimpleChanges): void;
|
ngOnChanges(changes: SimpleChanges): void;
|
||||||
ngOnDestroy(): void;
|
ngOnDestroy(): void;
|
||||||
viewToModelUpdate(newValue: any): void;
|
viewToModelUpdate(newValue: any): void;
|
||||||
|
@ -429,6 +431,7 @@ export declare class NgSelectOption implements OnDestroy {
|
||||||
export declare class PatternValidator implements Validator, OnChanges {
|
export declare class PatternValidator implements Validator, OnChanges {
|
||||||
pattern: string;
|
pattern: string;
|
||||||
ngOnChanges(changes: SimpleChanges): void;
|
ngOnChanges(changes: SimpleChanges): void;
|
||||||
|
registerOnChange(fn: () => void): void;
|
||||||
validate(c: AbstractControl): {
|
validate(c: AbstractControl): {
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
};
|
};
|
||||||
|
@ -441,6 +444,7 @@ export declare class ReactiveFormsModule {
|
||||||
/** @stable */
|
/** @stable */
|
||||||
export declare class RequiredValidator implements Validator {
|
export declare class RequiredValidator implements Validator {
|
||||||
required: boolean;
|
required: boolean;
|
||||||
|
registerOnChange(fn: () => void): void;
|
||||||
validate(c: AbstractControl): {
|
validate(c: AbstractControl): {
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
};
|
};
|
||||||
|
@ -472,6 +476,7 @@ export declare class SelectMultipleControlValueAccessor implements ControlValueA
|
||||||
|
|
||||||
/** @stable */
|
/** @stable */
|
||||||
export interface Validator {
|
export interface Validator {
|
||||||
|
registerOnChange?(fn: () => void): void;
|
||||||
validate(c: AbstractControl): {
|
validate(c: AbstractControl): {
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue