From 50acb96130f74ba1e82db27e49f1a3b508ab4154 Mon Sep 17 00:00:00 2001 From: Kara Erickson Date: Wed, 8 Jun 2016 14:06:20 -0700 Subject: [PATCH] fix(forms): update value and validity when controls are added Closes #8826 --- .../forms-deprecated/directives/ng_form.ts | 6 ++--- .../common/src/forms-deprecated/model.ts | 17 +++++++++--- .../test/forms-deprecated/model_spec.ts | 27 +++++++++++++++++++ tools/public_api_guard/public_api_spec.ts | 1 + 4 files changed, 44 insertions(+), 7 deletions(-) diff --git a/modules/@angular/common/src/forms-deprecated/directives/ng_form.ts b/modules/@angular/common/src/forms-deprecated/directives/ng_form.ts index da64f7f558..dfd20788c7 100644 --- a/modules/@angular/common/src/forms-deprecated/directives/ng_form.ts +++ b/modules/@angular/common/src/forms-deprecated/directives/ng_form.ts @@ -115,7 +115,7 @@ export class NgForm extends ControlContainer implements Form { var container = this._findContainer(dir.path); var ctrl = new Control(); setUpControl(ctrl, dir); - container.addControl(dir.name, ctrl); + container.registerControl(dir.name, ctrl); ctrl.updateValueAndValidity({emitEvent: false}); }); } @@ -127,7 +127,6 @@ export class NgForm extends ControlContainer implements Form { var container = this._findContainer(dir.path); if (isPresent(container)) { container.removeControl(dir.name); - container.updateValueAndValidity({emitEvent: false}); } }); } @@ -137,7 +136,7 @@ export class NgForm extends ControlContainer implements Form { var container = this._findContainer(dir.path); var group = new ControlGroup({}); setUpControlGroup(group, dir); - container.addControl(dir.name, group); + container.registerControl(dir.name, group); group.updateValueAndValidity({emitEvent: false}); }); } @@ -147,7 +146,6 @@ export class NgForm extends ControlContainer implements Form { var container = this._findContainer(dir.path); if (isPresent(container)) { container.removeControl(dir.name); - container.updateValueAndValidity({emitEvent: false}); } }); } diff --git a/modules/@angular/common/src/forms-deprecated/model.ts b/modules/@angular/common/src/forms-deprecated/model.ts index 4efa0d5eb8..3741d2e079 100644 --- a/modules/@angular/common/src/forms-deprecated/model.ts +++ b/modules/@angular/common/src/forms-deprecated/model.ts @@ -350,17 +350,28 @@ export class ControlGroup extends AbstractControl { } /** - * Add a control to this group. + * Register a control with the group's list of controls. */ - addControl(name: string, control: AbstractControl): void { + registerControl(name: string, control: AbstractControl): void { this.controls[name] = control; control.setParent(this); } + /** + * Add a control to this group. + */ + addControl(name: string, control: AbstractControl): void { + this.registerControl(name, control); + this.updateValueAndValidity(); + } + /** * Remove a control from this group. */ - removeControl(name: string): void { StringMapWrapper.delete(this.controls, name); } + removeControl(name: string): void { + StringMapWrapper.delete(this.controls, name); + this.updateValueAndValidity(); + } /** * Mark the named control as non-optional. diff --git a/modules/@angular/common/test/forms-deprecated/model_spec.ts b/modules/@angular/common/test/forms-deprecated/model_spec.ts index 251b1d4d7b..4d20589b89 100644 --- a/modules/@angular/common/test/forms-deprecated/model_spec.ts +++ b/modules/@angular/common/test/forms-deprecated/model_spec.ts @@ -351,6 +351,33 @@ export function main() { }); }); + describe("adding and removing controls", () => { + it("should update value and validity when control is added", () => { + var g = new ControlGroup({ "one": new Control("1") }); + expect(g.value).toEqual({"one": "1"}); + expect(g.valid).toBe(true); + + g.addControl("two", new Control("2", Validators.minLength(10))); + + expect(g.value).toEqual({"one": "1","two": "2"}); + expect(g.valid).toBe(false); + }); + + it("should update value and validity when control is removed", () => { + var g = new ControlGroup({ + "one": new Control("1"), + "two": new Control("2", Validators.minLength(10)) + }); + expect(g.value).toEqual({"one": "1", "two": "2"}); + expect(g.valid).toBe(false); + + g.removeControl("two"); + + expect(g.value).toEqual({"one": "1"}); + expect(g.valid).toBe(true); + }); + }); + describe("errors", () => { it("should run the validator when the value changes", () => { var simpleValidator = (c) => diff --git a/tools/public_api_guard/public_api_spec.ts b/tools/public_api_guard/public_api_spec.ts index 282edde4ae..97c01f8abd 100644 --- a/tools/public_api_guard/public_api_spec.ts +++ b/tools/public_api_guard/public_api_spec.ts @@ -771,6 +771,7 @@ const COMMON = [ 'ControlGroup.controls:{[key:string]:AbstractControl}', 'ControlGroup.exclude(controlName:string):void', 'ControlGroup.include(controlName:string):void', + 'ControlGroup.registerControl(name:string, control:AbstractControl):void', 'ControlGroup.removeControl(name:string):void', 'ControlValueAccessor', 'ControlValueAccessor.registerOnChange(fn:any):void',