fix(forms): handle control change in NgFormControl

when a new Control instance is bound to the directive, use the new instance, not the old one
This commit is contained in:
mikael 2015-09-28 10:06:52 +10:00 committed by Victor Savkin
parent 485c85bfe7
commit d29a9a99aa
3 changed files with 28 additions and 15 deletions

View File

@ -8,7 +8,7 @@ import {NgControl} from './ng_control';
import {Control} from '../model'; import {Control} from '../model';
import {Validators, NG_VALIDATORS} from '../validators'; import {Validators, NG_VALIDATORS} from '../validators';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor'; import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';
import {setUpControl, isPropertyUpdated, selectValueAccessor} from './shared'; import {setUpControl, isPropertyUpdated, isControlChanged, selectValueAccessor} from './shared';
const formControlBinding = const formControlBinding =
CONST_EXPR(new Provider(NgControl, {useExisting: forwardRef(() => NgFormControl)})); CONST_EXPR(new Provider(NgControl, {useExisting: forwardRef(() => NgFormControl)}));
@ -70,8 +70,6 @@ const formControlBinding =
export class NgFormControl extends NgControl implements OnChanges { export class NgFormControl extends NgControl implements OnChanges {
form: Control; form: Control;
update = new EventEmitter(); update = new EventEmitter();
/** @internal */
_added = false;
model: any; model: any;
viewModel: any; viewModel: any;
validators: Function[]; validators: Function[];
@ -84,10 +82,9 @@ export class NgFormControl extends NgControl implements OnChanges {
} }
onChanges(changes: {[key: string]: SimpleChange}): void { onChanges(changes: {[key: string]: SimpleChange}): void {
if (!this._added) { if (isControlChanged(changes)) {
setUpControl(this.form, this); setUpControl(this.form, this);
this.form.updateValidity(); this.form.updateValidity();
this._added = true;
} }
if (isPropertyUpdated(changes, this.viewModel)) { if (isPropertyUpdated(changes, this.viewModel)) {
this.form.updateValue(this.model); this.form.updateValue(this.model);

View File

@ -60,6 +60,12 @@ export function isPropertyUpdated(changes: {[key: string]: any}, viewModel: any)
return !looseIdentical(viewModel, change.currentValue); return !looseIdentical(viewModel, change.currentValue);
} }
export function isControlChanged(changes: {[key: string]: any}): boolean {
if (!StringMapWrapper.contains(changes, "form")) return false;
var change = changes["form"];
return change.previousValue !== change.currentValue;
}
// TODO: vsavkin remove it once https://github.com/angular/angular/issues/3011 is implemented // TODO: vsavkin remove it once https://github.com/angular/angular/issues/3011 is implemented
export function selectValueAccessor(dir: NgControl, valueAccessors: ControlValueAccessor[]): export function selectValueAccessor(dir: NgControl, valueAccessors: ControlValueAccessor[]):
ControlValueAccessor { ControlValueAccessor {

View File

@ -38,6 +38,7 @@ import {
import {selectValueAccessor} from 'angular2/src/core/forms/directives/shared'; import {selectValueAccessor} from 'angular2/src/core/forms/directives/shared';
import {SimpleChange} from 'angular2/src/core/change_detection';
class DummyControlValueAccessor implements ControlValueAccessor { class DummyControlValueAccessor implements ControlValueAccessor {
writtenValue; writtenValue;
@ -275,6 +276,16 @@ export function main() {
describe("NgFormControl", () => { describe("NgFormControl", () => {
var controlDir; var controlDir;
var control; var control;
var checkProperties = function(control) {
expect(controlDir.control).toBe(control);
expect(controlDir.value).toBe(control.value);
expect(controlDir.valid).toBe(control.valid);
expect(controlDir.errors).toBe(control.errors);
expect(controlDir.pristine).toBe(control.pristine);
expect(controlDir.dirty).toBe(control.dirty);
expect(controlDir.touched).toBe(control.touched);
expect(controlDir.untouched).toBe(control.untouched);
};
beforeEach(() => { beforeEach(() => {
controlDir = new NgFormControl([], [defaultAccessor]); controlDir = new NgFormControl([], [defaultAccessor]);
@ -284,15 +295,14 @@ export function main() {
controlDir.form = control; controlDir.form = control;
}); });
it("should reexport control properties", () => { it("should reexport control properties", () => { checkProperties(control); });
expect(controlDir.control).toBe(control);
expect(controlDir.value).toBe(control.value); it("should reexport new control properties", () => {
expect(controlDir.valid).toBe(control.valid); var newControl = new Control(null);
expect(controlDir.errors).toBe(control.errors); controlDir.form = newControl;
expect(controlDir.pristine).toBe(control.pristine); controlDir.onChanges({"form": new SimpleChange(control, newControl)});
expect(controlDir.dirty).toBe(control.dirty);
expect(controlDir.touched).toBe(control.touched); checkProperties(newControl);
expect(controlDir.untouched).toBe(control.untouched);
}); });
it("should set up validator", () => { it("should set up validator", () => {
@ -301,7 +311,7 @@ export function main() {
expect(control.valid).toBe(true); expect(control.valid).toBe(true);
// this will add the required validator and recalculate the validity // this will add the required validator and recalculate the validity
controlDir.onChanges({}); controlDir.onChanges({"form": new SimpleChange(null, control)});
expect(control.valid).toBe(false); expect(control.valid).toBe(false);
}); });