From 212f8dbde7039c2dd76aa75ee38316aad29e9d33 Mon Sep 17 00:00:00 2001 From: Kara Erickson Date: Tue, 20 Sep 2016 09:08:12 -0700 Subject: [PATCH] fix(forms): disable all radios with disable() --- modules/@angular/forms/src/model.ts | 12 +++-- .../forms/test/reactive_integration_spec.ts | 48 +++++++++++++++++++ .../forms/test/template_integration_spec.ts | 35 +++++++++++++- 3 files changed, 89 insertions(+), 6 deletions(-) diff --git a/modules/@angular/forms/src/model.ts b/modules/@angular/forms/src/model.ts index 7738c754bf..5a9ac3bd08 100644 --- a/modules/@angular/forms/src/model.ts +++ b/modules/@angular/forms/src/model.ts @@ -334,7 +334,7 @@ export abstract class AbstractControl { } this._updateAncestors(onlySelf); - this._onDisabledChange(true); + this._onDisabledChange.forEach((changeFn) => changeFn(true)); } /** @@ -350,7 +350,7 @@ export abstract class AbstractControl { this.updateValueAndValidity({onlySelf: true, emitEvent: emitEvent}); this._updateAncestors(onlySelf); - this._onDisabledChange(false); + this._onDisabledChange.forEach((changeFn) => changeFn(false)); } private _updateAncestors(onlySelf: boolean) { @@ -595,7 +595,7 @@ export abstract class AbstractControl { } /** @internal */ - _onDisabledChange(isDisabled: boolean): void {} + _onDisabledChange: Function[] = []; /** @internal */ _isBoxedValue(formState: any): boolean { @@ -770,14 +770,16 @@ export class FormControl extends AbstractControl { */ _clearChangeFns(): void { this._onChange = []; - this._onDisabledChange = null; + this._onDisabledChange = []; this._onCollectionChange = () => {}; } /** * Register a listener for disabled events. */ - registerOnDisabledChange(fn: (isDisabled: boolean) => void): void { this._onDisabledChange = fn; } + registerOnDisabledChange(fn: (isDisabled: boolean) => void): void { + this._onDisabledChange.push(fn); + } /** * @internal diff --git a/modules/@angular/forms/test/reactive_integration_spec.ts b/modules/@angular/forms/test/reactive_integration_spec.ts index c763d04c64..d4763e0f39 100644 --- a/modules/@angular/forms/test/reactive_integration_spec.ts +++ b/modules/@angular/forms/test/reactive_integration_spec.ts @@ -1022,6 +1022,54 @@ export function main() { }); + it('should disable all radio buttons when disable() is called', () => { + const fixture = TestBed.createComponent(FormControlRadioButtons); + const form = + new FormGroup({food: new FormControl('fish'), drink: new FormControl('cola')}); + fixture.componentInstance.form = form; + fixture.detectChanges(); + + const inputs = fixture.debugElement.queryAll(By.css('input')); + expect(inputs[0].nativeElement.disabled).toEqual(false); + expect(inputs[1].nativeElement.disabled).toEqual(false); + expect(inputs[2].nativeElement.disabled).toEqual(false); + expect(inputs[3].nativeElement.disabled).toEqual(false); + + form.get('food').disable(); + expect(inputs[0].nativeElement.disabled).toEqual(true); + expect(inputs[1].nativeElement.disabled).toEqual(true); + expect(inputs[2].nativeElement.disabled).toEqual(false); + expect(inputs[3].nativeElement.disabled).toEqual(false); + + form.disable(); + expect(inputs[0].nativeElement.disabled).toEqual(true); + expect(inputs[1].nativeElement.disabled).toEqual(true); + expect(inputs[2].nativeElement.disabled).toEqual(true); + expect(inputs[3].nativeElement.disabled).toEqual(true); + + form.enable(); + expect(inputs[0].nativeElement.disabled).toEqual(false); + expect(inputs[1].nativeElement.disabled).toEqual(false); + expect(inputs[2].nativeElement.disabled).toEqual(false); + expect(inputs[3].nativeElement.disabled).toEqual(false); + }); + + it('should disable all radio buttons when initially disabled', () => { + const fixture = TestBed.createComponent(FormControlRadioButtons); + const form = new FormGroup({ + food: new FormControl({value: 'fish', disabled: true}), + drink: new FormControl('cola') + }); + fixture.componentInstance.form = form; + fixture.detectChanges(); + + const inputs = fixture.debugElement.queryAll(By.css('input')); + expect(inputs[0].nativeElement.disabled).toEqual(true); + expect(inputs[1].nativeElement.disabled).toEqual(true); + expect(inputs[2].nativeElement.disabled).toEqual(false); + expect(inputs[3].nativeElement.disabled).toEqual(false); + }); + }); describe('custom value accessors', () => { diff --git a/modules/@angular/forms/test/template_integration_spec.ts b/modules/@angular/forms/test/template_integration_spec.ts index 271578159d..90d7f78bfc 100644 --- a/modules/@angular/forms/test/template_integration_spec.ts +++ b/modules/@angular/forms/test/template_integration_spec.ts @@ -445,6 +445,39 @@ export function main() { expect(input.nativeElement.disabled).toEqual(false); })); + it('should disable radio controls properly with programmatic call', fakeAsync(() => { + const fixture = TestBed.createComponent(NgModelRadioForm); + fixture.componentInstance.food = 'fish'; + fixture.detectChanges(); + tick(); + + const form = fixture.debugElement.children[0].injector.get(NgForm); + form.control.get('food').disable(); + tick(); + + const inputs = fixture.debugElement.queryAll(By.css('input')); + expect(inputs[0].nativeElement.disabled).toBe(true); + expect(inputs[1].nativeElement.disabled).toBe(true); + expect(inputs[2].nativeElement.disabled).toBe(false); + expect(inputs[3].nativeElement.disabled).toBe(false); + + form.control.disable(); + tick(); + + expect(inputs[0].nativeElement.disabled).toBe(true); + expect(inputs[1].nativeElement.disabled).toBe(true); + expect(inputs[2].nativeElement.disabled).toBe(true); + expect(inputs[3].nativeElement.disabled).toBe(true); + + form.control.enable(); + tick(); + + expect(inputs[0].nativeElement.disabled).toBe(false); + expect(inputs[1].nativeElement.disabled).toBe(false); + expect(inputs[2].nativeElement.disabled).toBe(false); + expect(inputs[3].nativeElement.disabled).toBe(false); + })); + }); describe('radio controls', () => { @@ -928,7 +961,7 @@ class NgModelOptionsStandalone {
- +