Skip to content

Commit c8bd7fc

Browse files
committed
fix(radio): only call change callback with user input
1 parent 3bb667e commit c8bd7fc

File tree

2 files changed

+20
-16
lines changed

2 files changed

+20
-16
lines changed

src/lib/radio/radio.spec.ts

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
1+
import {async, ComponentFixture, TestBed, fakeAsync, tick} from '@angular/core/testing';
22
import {NgControl, FormsModule} from '@angular/forms';
33
import {Component, DebugElement} from '@angular/core';
44
import {By} from '@angular/platform-browser';
@@ -223,7 +223,7 @@ describe('MdRadio', () => {
223223
let groupDebugElement: DebugElement;
224224
let groupNativeElement: HTMLElement;
225225
let radioDebugElements: DebugElement[];
226-
let radioNativeElements: HTMLElement[];
226+
let innerRadios: DebugElement[];
227227
let radioLabelElements: HTMLLabelElement[];
228228
let groupInstance: MdRadioGroup;
229229
let radioInstances: MdRadioButton[];
@@ -242,8 +242,8 @@ describe('MdRadio', () => {
242242
groupNgControl = groupDebugElement.injector.get(NgControl);
243243

244244
radioDebugElements = fixture.debugElement.queryAll(By.directive(MdRadioButton));
245-
radioNativeElements = radioDebugElements.map(debugEl => debugEl.nativeElement);
246245
radioInstances = radioDebugElements.map(debugEl => debugEl.componentInstance);
246+
innerRadios = fixture.debugElement.queryAll(By.css('input[type="radio"]'));
247247

248248
radioLabelElements = radioDebugElements
249249
.map(debugEl => debugEl.query(By.css('label')).nativeElement);
@@ -280,16 +280,16 @@ describe('MdRadio', () => {
280280
expect(groupNgControl.pristine).toBe(true);
281281
expect(groupNgControl.touched).toBe(false);
282282

283-
// After changing the value programmatically, the control should become dirty (not pristine),
283+
// After changing the value programmatically, the control should stay pristine
284284
// but remain untouched.
285285
radioInstances[1].checked = true;
286286
fixture.detectChanges();
287287

288288
expect(groupNgControl.valid).toBe(true);
289-
expect(groupNgControl.pristine).toBe(false);
289+
expect(groupNgControl.pristine).toBe(true);
290290
expect(groupNgControl.touched).toBe(false);
291291

292-
// After a user interaction occurs (such as a click), the control should remain dirty and
292+
// After a user interaction occurs (such as a click), the control should become dirty and
293293
// now also be touched.
294294
radioLabelElements[2].click();
295295
fixture.detectChanges();
@@ -299,27 +299,31 @@ describe('MdRadio', () => {
299299
expect(groupNgControl.touched).toBe(true);
300300
});
301301

302-
it('should update the ngModel value when selecting a radio button', () => {
303-
radioInstances[1].checked = true;
302+
it('should write to the radio button based on ngModel', fakeAsync(() => {
303+
testComponent.modelValue = 'chocolate';
304+
fixture.detectChanges();
305+
tick();
304306
fixture.detectChanges();
305307

308+
expect(innerRadios[1].nativeElement.checked).toBe(true);
309+
}));
310+
311+
it('should update the ngModel value when selecting a radio button', () => {
312+
innerRadios[1].nativeElement.dispatchEvent(new Event('change'));
313+
fixture.detectChanges();
306314
expect(testComponent.modelValue).toBe('chocolate');
307315
});
308316

309317
it('should update the model before firing change event', () => {
310318
expect(testComponent.modelValue).toBeUndefined();
311319
expect(testComponent.lastEvent).toBeUndefined();
312320

313-
groupInstance.value = 'chocolate';
321+
innerRadios[1].nativeElement.dispatchEvent(new Event('change'));
314322
fixture.detectChanges();
315-
316-
expect(testComponent.modelValue).toBe('chocolate');
317323
expect(testComponent.lastEvent.value).toBe('chocolate');
318324

319-
groupInstance.value = 'vanilla';
325+
innerRadios[0].nativeElement.dispatchEvent(new Event('change'));
320326
fixture.detectChanges();
321-
322-
expect(testComponent.modelValue).toBe('vanilla');
323327
expect(testComponent.lastEvent.value).toBe('vanilla');
324328
});
325329
});

src/lib/radio/radio.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export class MdRadioGroup implements AfterContentInit, ControlValueAccessor {
7878
private _isInitialized: boolean = false;
7979

8080
/** The method to be called in order to update ngModel */
81-
private _controlValueAccessorChangeFn: (value: any) => void = (value) => {};
81+
_controlValueAccessorChangeFn: (value: any) => void = (value) => {};
8282

8383
/** onTouch function registered via registerOnTouch (ControlValueAccessor). */
8484
onTouched: () => any = () => {};
@@ -198,7 +198,6 @@ export class MdRadioGroup implements AfterContentInit, ControlValueAccessor {
198198
let event = new MdRadioChange();
199199
event.source = this._selected;
200200
event.value = this._value;
201-
this._controlValueAccessorChangeFn(event.value);
202201
this.change.emit(event);
203202
}
204203

@@ -405,6 +404,7 @@ export class MdRadioButton implements OnInit {
405404
event.stopPropagation();
406405

407406
this.checked = true;
407+
this.radioGroup._controlValueAccessorChangeFn(this.value);
408408
this._emitChangeEvent();
409409

410410
if (this.radioGroup) {

0 commit comments

Comments
 (0)