feat(forms): support adding validators to ControlGroup via template
Closes #4954
This commit is contained in:
parent
f98faf0702
commit
758062807a
|
@ -21,4 +21,6 @@ export class AbstractControlDirective {
|
||||||
get touched(): boolean { return isPresent(this.control) ? this.control.touched : null; }
|
get touched(): boolean { return isPresent(this.control) ? this.control.touched : null; }
|
||||||
|
|
||||||
get untouched(): boolean { return isPresent(this.control) ? this.control.untouched : null; }
|
get untouched(): boolean { return isPresent(this.control) ? this.control.untouched : null; }
|
||||||
|
|
||||||
|
get path(): string[] { return null; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@ export class NgControl extends AbstractControlDirective {
|
||||||
valueAccessor: ControlValueAccessor = null;
|
valueAccessor: ControlValueAccessor = null;
|
||||||
|
|
||||||
get validator(): Function { return null; }
|
get validator(): Function { return null; }
|
||||||
get path(): string[] { return null; }
|
|
||||||
|
|
||||||
viewToModelUpdate(newValue: any): void {}
|
viewToModelUpdate(newValue: any): void {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import {OnInit, OnDestroy} from 'angular2/lifecycle_hooks';
|
import {OnInit, OnDestroy} from 'angular2/lifecycle_hooks';
|
||||||
import {Directive} from 'angular2/src/core/metadata';
|
import {Directive} from 'angular2/src/core/metadata';
|
||||||
import {Inject, Host, SkipSelf, forwardRef, Provider} from 'angular2/src/core/di';
|
import {Optional, Inject, Host, SkipSelf, forwardRef, Provider} from 'angular2/src/core/di';
|
||||||
import {ListWrapper} from 'angular2/src/core/facade/collection';
|
import {ListWrapper} from 'angular2/src/core/facade/collection';
|
||||||
import {CONST_EXPR} from 'angular2/src/core/facade/lang';
|
import {CONST_EXPR} from 'angular2/src/core/facade/lang';
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import {ControlContainer} from './control_container';
|
||||||
import {controlPath} from './shared';
|
import {controlPath} from './shared';
|
||||||
import {ControlGroup} from '../model';
|
import {ControlGroup} from '../model';
|
||||||
import {Form} from './form_interface';
|
import {Form} from './form_interface';
|
||||||
|
import {Validators, NG_VALIDATORS} from '../validators';
|
||||||
|
|
||||||
const controlGroupBinding =
|
const controlGroupBinding =
|
||||||
CONST_EXPR(new Provider(ControlContainer, {useExisting: forwardRef(() => NgControlGroup)}));
|
CONST_EXPR(new Provider(ControlContainer, {useExisting: forwardRef(() => NgControlGroup)}));
|
||||||
|
@ -60,9 +61,14 @@ export class NgControlGroup extends ControlContainer implements OnInit,
|
||||||
OnDestroy {
|
OnDestroy {
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_parent: ControlContainer;
|
_parent: ControlContainer;
|
||||||
constructor(@Host() @SkipSelf() _parent: ControlContainer) {
|
|
||||||
|
private _validators: Function[];
|
||||||
|
|
||||||
|
constructor(@Host() @SkipSelf() parent: ControlContainer,
|
||||||
|
@Optional() @Inject(NG_VALIDATORS) validators: Function[]) {
|
||||||
super();
|
super();
|
||||||
this._parent = _parent;
|
this._parent = parent;
|
||||||
|
this._validators = validators;
|
||||||
}
|
}
|
||||||
|
|
||||||
onInit(): void { this.formDirective.addControlGroup(this); }
|
onInit(): void { this.formDirective.addControlGroup(this); }
|
||||||
|
@ -74,4 +80,6 @@ export class NgControlGroup extends ControlContainer implements OnInit,
|
||||||
get path(): string[] { return controlPath(this.name, this._parent); }
|
get path(): string[] { return controlPath(this.name, this._parent); }
|
||||||
|
|
||||||
get formDirective(): Form { return this._parent.formDirective; }
|
get formDirective(): Form { return this._parent.formDirective; }
|
||||||
|
|
||||||
|
get validator(): Function { return Validators.compose(this._validators); }
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,13 +7,14 @@ import {
|
||||||
import {StringMapWrapper, ListWrapper} from 'angular2/src/core/facade/collection';
|
import {StringMapWrapper, ListWrapper} from 'angular2/src/core/facade/collection';
|
||||||
import {isPresent, isBlank, CONST_EXPR} from 'angular2/src/core/facade/lang';
|
import {isPresent, isBlank, CONST_EXPR} from 'angular2/src/core/facade/lang';
|
||||||
import {Directive} from 'angular2/src/core/metadata';
|
import {Directive} from 'angular2/src/core/metadata';
|
||||||
import {forwardRef, Provider} from 'angular2/src/core/di';
|
import {forwardRef, Provider, Optional, Inject} from 'angular2/src/core/di';
|
||||||
import {NgControl} from './ng_control';
|
import {NgControl} from './ng_control';
|
||||||
import {Form} from './form_interface';
|
import {Form} from './form_interface';
|
||||||
import {NgControlGroup} from './ng_control_group';
|
import {NgControlGroup} from './ng_control_group';
|
||||||
import {ControlContainer} from './control_container';
|
import {ControlContainer} from './control_container';
|
||||||
import {AbstractControl, ControlGroup, Control} from '../model';
|
import {AbstractControl, ControlGroup, Control} from '../model';
|
||||||
import {setUpControl} from './shared';
|
import {setUpControl, setUpControlGroup} from './shared';
|
||||||
|
import {Validators, NG_VALIDATORS} from '../validators';
|
||||||
|
|
||||||
const formDirectiveProvider =
|
const formDirectiveProvider =
|
||||||
CONST_EXPR(new Provider(ControlContainer, {useExisting: forwardRef(() => NgForm)}));
|
CONST_EXPR(new Provider(ControlContainer, {useExisting: forwardRef(() => NgForm)}));
|
||||||
|
@ -87,9 +88,14 @@ const formDirectiveProvider =
|
||||||
exportAs: 'form'
|
exportAs: 'form'
|
||||||
})
|
})
|
||||||
export class NgForm extends ControlContainer implements Form {
|
export class NgForm extends ControlContainer implements Form {
|
||||||
form: ControlGroup = new ControlGroup({});
|
form: ControlGroup;
|
||||||
ngSubmit = new EventEmitter();
|
ngSubmit = new EventEmitter();
|
||||||
|
|
||||||
|
constructor(@Optional() @Inject(NG_VALIDATORS) validators: Function[]) {
|
||||||
|
super();
|
||||||
|
this.form = new ControlGroup({}, null, Validators.compose(validators));
|
||||||
|
}
|
||||||
|
|
||||||
get formDirective(): Form { return this; }
|
get formDirective(): Form { return this; }
|
||||||
|
|
||||||
get control(): ControlGroup { return this.form; }
|
get control(): ControlGroup { return this.form; }
|
||||||
|
@ -124,6 +130,7 @@ export class NgForm extends ControlContainer implements Form {
|
||||||
this._later(_ => {
|
this._later(_ => {
|
||||||
var container = this._findContainer(dir.path);
|
var container = this._findContainer(dir.path);
|
||||||
var group = new ControlGroup({});
|
var group = new ControlGroup({});
|
||||||
|
setUpControlGroup(group, dir);
|
||||||
container.addControl(dir.name, group);
|
container.addControl(dir.name, group);
|
||||||
group.updateValueAndValidity({emitEvent: false});
|
group.updateValueAndValidity({emitEvent: false});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
import {CONST_EXPR} from 'angular2/src/core/facade/lang';
|
import {CONST_EXPR} from 'angular2/src/core/facade/lang';
|
||||||
import {ListWrapper} from 'angular2/src/core/facade/collection';
|
import {ListWrapper, StringMapWrapper} from 'angular2/src/core/facade/collection';
|
||||||
import {ObservableWrapper, EventEmitter} from 'angular2/src/core/facade/async';
|
import {ObservableWrapper, EventEmitter} from 'angular2/src/core/facade/async';
|
||||||
|
import {SimpleChange} from 'angular2/src/core/change_detection';
|
||||||
|
|
||||||
import {OnChanges} from 'angular2/lifecycle_hooks';
|
import {OnChanges} from 'angular2/lifecycle_hooks';
|
||||||
import {Directive} from 'angular2/src/core/metadata';
|
import {Directive} from 'angular2/src/core/metadata';
|
||||||
import {forwardRef, Provider} from 'angular2/src/core/di';
|
import {forwardRef, Provider, Inject, Optional} from 'angular2/src/core/di';
|
||||||
import {NgControl} from './ng_control';
|
import {NgControl} from './ng_control';
|
||||||
import {NgControlGroup} from './ng_control_group';
|
import {NgControlGroup} from './ng_control_group';
|
||||||
import {ControlContainer} from './control_container';
|
import {ControlContainer} from './control_container';
|
||||||
import {Form} from './form_interface';
|
import {Form} from './form_interface';
|
||||||
import {Control, ControlGroup} from '../model';
|
import {Control, ControlGroup} from '../model';
|
||||||
import {setUpControl} from './shared';
|
import {setUpControl, setUpControlGroup} from './shared';
|
||||||
|
import {Validators, NG_VALIDATORS} from '../validators';
|
||||||
|
|
||||||
const formDirectiveProvider =
|
const formDirectiveProvider =
|
||||||
CONST_EXPR(new Provider(ControlContainer, {useExisting: forwardRef(() => NgFormModel)}));
|
CONST_EXPR(new Provider(ControlContainer, {useExisting: forwardRef(() => NgFormModel)}));
|
||||||
|
@ -100,8 +102,21 @@ export class NgFormModel extends ControlContainer implements Form,
|
||||||
form: ControlGroup = null;
|
form: ControlGroup = null;
|
||||||
directives: NgControl[] = [];
|
directives: NgControl[] = [];
|
||||||
ngSubmit = new EventEmitter();
|
ngSubmit = new EventEmitter();
|
||||||
|
private _validators: Function[];
|
||||||
|
|
||||||
onChanges(_): void { this._updateDomValue(); }
|
constructor(@Optional() @Inject(NG_VALIDATORS) validators: Function[]) {
|
||||||
|
super();
|
||||||
|
this._validators = validators;
|
||||||
|
}
|
||||||
|
|
||||||
|
onChanges(changes: {[key: string]: SimpleChange}): void {
|
||||||
|
if (StringMapWrapper.contains(changes, "form")) {
|
||||||
|
var c = Validators.compose(this._validators);
|
||||||
|
this.form.validator = Validators.compose([this.form.validator, c]);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._updateDomValue();
|
||||||
|
}
|
||||||
|
|
||||||
get formDirective(): Form { return this; }
|
get formDirective(): Form { return this; }
|
||||||
|
|
||||||
|
@ -120,7 +135,11 @@ export class NgFormModel extends ControlContainer implements Form,
|
||||||
|
|
||||||
removeControl(dir: NgControl): void { ListWrapper.remove(this.directives, dir); }
|
removeControl(dir: NgControl): void { ListWrapper.remove(this.directives, dir); }
|
||||||
|
|
||||||
addControlGroup(dir: NgControlGroup) {}
|
addControlGroup(dir: NgControlGroup) {
|
||||||
|
var ctrl: any = this.form.find(dir.path);
|
||||||
|
setUpControlGroup(ctrl, dir);
|
||||||
|
ctrl.updateValueAndValidity({emitEvent: false});
|
||||||
|
}
|
||||||
|
|
||||||
removeControlGroup(dir: NgControlGroup) {}
|
removeControlGroup(dir: NgControlGroup) {}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,9 @@ import {BaseException, WrappedException} from 'angular2/src/core/facade/exceptio
|
||||||
|
|
||||||
import {ControlContainer} from './control_container';
|
import {ControlContainer} from './control_container';
|
||||||
import {NgControl} from './ng_control';
|
import {NgControl} from './ng_control';
|
||||||
import {Control} from '../model';
|
import {AbstractControlDirective} from './abstract_control_directive';
|
||||||
|
import {NgControlGroup} from './ng_control_group';
|
||||||
|
import {Control, ControlGroup} from '../model';
|
||||||
import {Validators} from '../validators';
|
import {Validators} from '../validators';
|
||||||
import {ControlValueAccessor} from './control_value_accessor';
|
import {ControlValueAccessor} from './control_value_accessor';
|
||||||
import {ElementRef, QueryList} from 'angular2/src/core/linker';
|
import {ElementRef, QueryList} from 'angular2/src/core/linker';
|
||||||
|
@ -42,7 +44,12 @@ export function setUpControl(control: Control, dir: NgControl): void {
|
||||||
dir.valueAccessor.registerOnTouched(() => control.markAsTouched());
|
dir.valueAccessor.registerOnTouched(() => control.markAsTouched());
|
||||||
}
|
}
|
||||||
|
|
||||||
function _throwError(dir: NgControl, message: string): void {
|
export function setUpControlGroup(control: ControlGroup, dir: NgControlGroup) {
|
||||||
|
if (isBlank(control)) _throwError(dir, "Cannot find control");
|
||||||
|
control.validator = Validators.compose([control.validator, dir.validator]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _throwError(dir: AbstractControlDirective, message: string): void {
|
||||||
var path = dir.path.join(" -> ");
|
var path = dir.path.join(" -> ");
|
||||||
throw new BaseException(`${message} '${path}'`);
|
throw new BaseException(`${message} '${path}'`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,8 +105,12 @@ export function main() {
|
||||||
var loginControlDir;
|
var loginControlDir;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
form = new NgFormModel();
|
form = new NgFormModel([]);
|
||||||
formModel = new ControlGroup({"login": new Control(null)});
|
formModel = new ControlGroup({
|
||||||
|
"login": new Control(),
|
||||||
|
"passwords":
|
||||||
|
new ControlGroup({"password": new Control(), "passwordConfirm": new Control()})
|
||||||
|
});
|
||||||
form.form = formModel;
|
form.form = formModel;
|
||||||
|
|
||||||
loginControlDir = new NgControlName(form, [], [defaultAccessor]);
|
loginControlDir = new NgControlName(form, [], [defaultAccessor]);
|
||||||
|
@ -167,6 +171,26 @@ export function main() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("addControlGroup", () => {
|
||||||
|
var matchingPasswordsValidator = (g) => {
|
||||||
|
if (g.controls["password"].value != g.controls["passwordConfirm"].value) {
|
||||||
|
return {"differentPasswords": true};
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
it("should set up validator", () => {
|
||||||
|
var group = new NgControlGroup(form, [matchingPasswordsValidator]);
|
||||||
|
group.name = "passwords";
|
||||||
|
form.addControlGroup(group);
|
||||||
|
|
||||||
|
formModel.find(["passwords", "password"]).updateValue("somePassword");
|
||||||
|
|
||||||
|
expect(formModel.hasError("differentPasswords", ["passwords"])).toEqual(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("removeControl", () => {
|
describe("removeControl", () => {
|
||||||
it("should remove the directive to the list of directives included in the form", () => {
|
it("should remove the directive to the list of directives included in the form", () => {
|
||||||
form.addControl(loginControlDir);
|
form.addControl(loginControlDir);
|
||||||
|
@ -181,10 +205,22 @@ export function main() {
|
||||||
|
|
||||||
formModel.find(["login"]).updateValue("new value");
|
formModel.find(["login"]).updateValue("new value");
|
||||||
|
|
||||||
form.onChanges(null);
|
form.onChanges({});
|
||||||
|
|
||||||
expect((<any>loginControlDir.valueAccessor).writtenValue).toEqual("new value");
|
expect((<any>loginControlDir.valueAccessor).writtenValue).toEqual("new value");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should set up validator", () => {
|
||||||
|
var formValidator = (c) => ({"custom": true});
|
||||||
|
var f = new NgFormModel([formValidator]);
|
||||||
|
f.form = formModel;
|
||||||
|
f.onChanges({"form": formModel});
|
||||||
|
|
||||||
|
// trigger validation
|
||||||
|
formModel.controls["login"].updateValue("");
|
||||||
|
|
||||||
|
expect(formModel.errors).toEqual({"custom": true});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -195,10 +231,10 @@ export function main() {
|
||||||
var personControlGroupDir;
|
var personControlGroupDir;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
form = new NgForm();
|
form = new NgForm([]);
|
||||||
formModel = form.form;
|
formModel = form.form;
|
||||||
|
|
||||||
personControlGroupDir = new NgControlGroup(form);
|
personControlGroupDir = new NgControlGroup(form, []);
|
||||||
personControlGroupDir.name = "person";
|
personControlGroupDir.name = "person";
|
||||||
|
|
||||||
loginControlDir = new NgControlName(personControlGroupDir, null, [defaultAccessor]);
|
loginControlDir = new NgControlName(personControlGroupDir, null, [defaultAccessor]);
|
||||||
|
@ -246,6 +282,17 @@ export function main() {
|
||||||
|
|
||||||
// should update the form's value and validity
|
// should update the form's value and validity
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should set up validator", fakeAsync(() => {
|
||||||
|
var formValidator = (c) => ({"custom": true});
|
||||||
|
var f = new NgForm([formValidator]);
|
||||||
|
f.addControlGroup(personControlGroupDir);
|
||||||
|
f.addControl(loginControlDir);
|
||||||
|
|
||||||
|
flushMicrotasks();
|
||||||
|
|
||||||
|
expect(f.form.errors).toEqual({"custom": true});
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("NgControlGroup", () => {
|
describe("NgControlGroup", () => {
|
||||||
|
@ -255,9 +302,9 @@ export function main() {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
formModel = new ControlGroup({"login": new Control(null)});
|
formModel = new ControlGroup({"login": new Control(null)});
|
||||||
|
|
||||||
var parent = new NgFormModel();
|
var parent = new NgFormModel([]);
|
||||||
parent.form = new ControlGroup({"group": formModel});
|
parent.form = new ControlGroup({"group": formModel});
|
||||||
controlGroupDir = new NgControlGroup(parent);
|
controlGroupDir = new NgControlGroup(parent, []);
|
||||||
controlGroupDir.name = "group";
|
controlGroupDir.name = "group";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -356,7 +403,7 @@ export function main() {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
formModel = new Control("name");
|
formModel = new Control("name");
|
||||||
|
|
||||||
var parent = new NgFormModel();
|
var parent = new NgFormModel([]);
|
||||||
parent.form = new ControlGroup({"name": formModel});
|
parent.form = new ControlGroup({"name": formModel});
|
||||||
controlNameDir = new NgControlName(parent, [], [defaultAccessor]);
|
controlNameDir = new NgControlName(parent, [], [defaultAccessor]);
|
||||||
controlNameDir.name = "name";
|
controlNameDir.name = "name";
|
||||||
|
|
|
@ -24,6 +24,8 @@ import {
|
||||||
ControlGroup,
|
ControlGroup,
|
||||||
ControlValueAccessor,
|
ControlValueAccessor,
|
||||||
FORM_DIRECTIVES,
|
FORM_DIRECTIVES,
|
||||||
|
NG_VALIDATORS,
|
||||||
|
Provider,
|
||||||
NgControl,
|
NgControl,
|
||||||
NgIf,
|
NgIf,
|
||||||
NgFor,
|
NgFor,
|
||||||
|
@ -398,10 +400,10 @@ export function main() {
|
||||||
var form = new ControlGroup(
|
var form = new ControlGroup(
|
||||||
{"login": new Control(""), "min": new Control(""), "max": new Control("")});
|
{"login": new Control(""), "min": new Control(""), "max": new Control("")});
|
||||||
|
|
||||||
var t = `<div [ng-form-model]="form">
|
var t = `<div [ng-form-model]="form" login-is-empty-validator>
|
||||||
<input type="text" ng-control="login" required>
|
<input type="text" ng-control="login" required>
|
||||||
<input type="text" ng-control="min" minlength="3">
|
<input type="text" ng-control="min" minlength="3">
|
||||||
<input type="text" ng-control="max" maxlength="3">
|
<input type="text" ng-control="max" maxlength="3">
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
tcb.overrideTemplate(MyComp, t).createAsync(MyComp).then((rootTC) => {
|
tcb.overrideTemplate(MyComp, t).createAsync(MyComp).then((rootTC) => {
|
||||||
|
@ -423,6 +425,8 @@ export function main() {
|
||||||
expect(form.hasError("minlength", ["min"])).toEqual(true);
|
expect(form.hasError("minlength", ["min"])).toEqual(true);
|
||||||
expect(form.hasError("maxlength", ["max"])).toEqual(true);
|
expect(form.hasError("maxlength", ["max"])).toEqual(true);
|
||||||
|
|
||||||
|
expect(form.hasError("loginIsEmpty")).toEqual(true);
|
||||||
|
|
||||||
required.nativeElement.value = "1";
|
required.nativeElement.value = "1";
|
||||||
minLength.nativeElement.value = "123";
|
minLength.nativeElement.value = "123";
|
||||||
maxLength.nativeElement.value = "123";
|
maxLength.nativeElement.value = "123";
|
||||||
|
@ -914,8 +918,22 @@ class MyInput implements ControlValueAccessor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({selector: "my-comp"})
|
function loginIsEmptyGroupValidator(c: ControlGroup) {
|
||||||
@View({directives: [FORM_DIRECTIVES, WrappedValue, MyInput, NgIf, NgFor]})
|
return c.controls["login"].value == "" ? {"loginIsEmpty": true} : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Directive({
|
||||||
|
selector: '[login-is-empty-validator]',
|
||||||
|
providers: [new Provider(NG_VALIDATORS, {useValue: loginIsEmptyGroupValidator, multi: true})]
|
||||||
|
})
|
||||||
|
class LoginIsEmptyValidator {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: "my-comp",
|
||||||
|
template: '',
|
||||||
|
directives: [FORM_DIRECTIVES, WrappedValue, MyInput, NgIf, NgFor, LoginIsEmptyValidator]
|
||||||
|
})
|
||||||
class MyComp {
|
class MyComp {
|
||||||
form: any;
|
form: any;
|
||||||
name: string;
|
name: string;
|
||||||
|
|
|
@ -73,6 +73,7 @@ var NG_API = [
|
||||||
'AbstractControlDirective.untouched',
|
'AbstractControlDirective.untouched',
|
||||||
'AbstractControlDirective.valid',
|
'AbstractControlDirective.valid',
|
||||||
'AbstractControlDirective.value',
|
'AbstractControlDirective.value',
|
||||||
|
'AbstractControlDirective.path',
|
||||||
'AppRootUrl',
|
'AppRootUrl',
|
||||||
'AppRootUrl.value',
|
'AppRootUrl.value',
|
||||||
'AppRootUrl.value=',
|
'AppRootUrl.value=',
|
||||||
|
@ -657,6 +658,7 @@ var NG_API = [
|
||||||
'NgControlGroup.untouched',
|
'NgControlGroup.untouched',
|
||||||
'NgControlGroup.valid',
|
'NgControlGroup.valid',
|
||||||
'NgControlGroup.value',
|
'NgControlGroup.value',
|
||||||
|
'NgControlGroup.validator',
|
||||||
'NgControlStatus',
|
'NgControlStatus',
|
||||||
'NgControlStatus.ngClassDirty',
|
'NgControlStatus.ngClassDirty',
|
||||||
'NgControlStatus.ngClassInvalid',
|
'NgControlStatus.ngClassInvalid',
|
||||||
|
@ -1030,9 +1032,7 @@ var NG_API = [
|
||||||
'UpperCasePipe.transform()',
|
'UpperCasePipe.transform()',
|
||||||
'UrlResolver',
|
'UrlResolver',
|
||||||
'UrlResolver.resolve()',
|
'UrlResolver.resolve()',
|
||||||
'Validators#array()',
|
|
||||||
'Validators#compose()',
|
'Validators#compose()',
|
||||||
'Validators#group()',
|
|
||||||
'Validators#nullValidator()',
|
'Validators#nullValidator()',
|
||||||
'Validators#required()',
|
'Validators#required()',
|
||||||
'Validators#minLength()',
|
'Validators#minLength()',
|
||||||
|
|
Loading…
Reference in New Issue