diff --git a/modules/@angular/forms/src/directives/ng_model.ts b/modules/@angular/forms/src/directives/ng_model.ts index 5e32a25d775b5..91c12295345cd 100644 --- a/modules/@angular/forms/src/directives/ng_model.ts +++ b/modules/@angular/forms/src/directives/ng_model.ts @@ -200,7 +200,9 @@ export class NgModel extends NgControl implements OnChanges, private _updateDisabled(changes: SimpleChanges) { const disabledValue = changes['isDisabled'].currentValue; - const isDisabled = disabledValue != null && disabledValue != false; + + const isDisabled = + disabledValue === '' || (disabledValue && disabledValue !== 'false'); resolvedPromise.then(() => { if (isDisabled && !this.control.disabled) { diff --git a/modules/@angular/forms/test/directives_spec.ts b/modules/@angular/forms/test/directives_spec.ts index 877d1ec56b854..15286e7b95c14 100644 --- a/modules/@angular/forms/test/directives_spec.ts +++ b/modules/@angular/forms/test/directives_spec.ts @@ -485,7 +485,7 @@ export function main() { }); describe('NgModel', () => { - var ngModel: any /** TODO #9100 */; + let ngModel: NgModel; beforeEach(() => { ngModel = new NgModel( @@ -539,6 +539,45 @@ export function main() { expect(ngModel.control.errors).toEqual({'async': true}); })); + + it('should mark as disabled properly', fakeAsync(() => { + ngModel.ngOnChanges({isDisabled: new SimpleChange('', undefined)}); + tick(); + expect(ngModel.control.disabled).toEqual(false); + + ngModel.ngOnChanges({isDisabled: new SimpleChange('', null)}); + tick(); + expect(ngModel.control.disabled).toEqual(false); + + ngModel.ngOnChanges({isDisabled: new SimpleChange('', false)}); + tick(); + expect(ngModel.control.disabled).toEqual(false); + + ngModel.ngOnChanges({isDisabled: new SimpleChange('', 'false')}); + tick(); + expect(ngModel.control.disabled).toEqual(false); + + ngModel.ngOnChanges({isDisabled: new SimpleChange('', 0)}); + tick(); + expect(ngModel.control.disabled).toEqual(false); + + ngModel.ngOnChanges({isDisabled: new SimpleChange(null, '')}); + tick(); + expect(ngModel.control.disabled).toEqual(true); + + ngModel.ngOnChanges({isDisabled: new SimpleChange(null, 'true')}); + tick(); + expect(ngModel.control.disabled).toEqual(true); + + ngModel.ngOnChanges({isDisabled: new SimpleChange(null, true)}); + tick(); + expect(ngModel.control.disabled).toEqual(true); + + ngModel.ngOnChanges({isDisabled: new SimpleChange(null, 'anything else')}); + tick(); + expect(ngModel.control.disabled).toEqual(true); + + })); }); describe('FormControlName', () => { diff --git a/modules/@angular/forms/test/template_integration_spec.ts b/modules/@angular/forms/test/template_integration_spec.ts index 0af59cbfc090d..271578159dc1d 100644 --- a/modules/@angular/forms/test/template_integration_spec.ts +++ b/modules/@angular/forms/test/template_integration_spec.ts @@ -420,6 +420,31 @@ export function main() { }); })); + it('should disable a control with unbound disabled attr', fakeAsync(() => { + TestBed.overrideComponent(NgModelForm, { + set: { + template: ` +
+ +
+ `, + } + }); + const fixture = TestBed.createComponent(NgModelForm); + fixture.detectChanges(); + tick(); + const form = fixture.debugElement.children[0].injector.get(NgForm); + expect(form.control.get('name').disabled).toBe(true); + + const input = fixture.debugElement.query(By.css('input')); + expect(input.nativeElement.disabled).toEqual(true); + + form.control.enable(); + fixture.detectChanges(); + tick(); + expect(input.nativeElement.disabled).toEqual(false); + })); + }); describe('radio controls', () => {