Skip to content

Commit 6f21d10

Browse files
committed
update: button-toggle should emit change event when native input does.
1 parent 9e3fbd6 commit 6f21d10

File tree

3 files changed

+33
-10
lines changed

3 files changed

+33
-10
lines changed

src/components/button-toggle/button-toggle.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
[checked]="checked"
66
[disabled]="disabled"
77
[name]="name"
8-
(change)="_onInputChange($event)">
8+
(change)="_onInputChange($event)"
9+
(click)="_onInputClick($event)">
910

1011
<div class="md-button-toggle-label-content">
1112
<ng-content></ng-content>

src/components/button-toggle/button-toggle.spec.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,13 @@ describe('MdButtonToggle', () => {
4141
}));
4242

4343
describe('inside of an exclusive selection group', () => {
44+
4445
let fixture: ComponentFixture<ButtonTogglesInsideButtonToggleGroup>;
4546
let groupDebugElement: DebugElement;
4647
let groupNativeElement: HTMLElement;
4748
let buttonToggleDebugElements: DebugElement[];
4849
let buttonToggleNativeElements: HTMLElement[];
50+
let buttonToggleLabelElements: HTMLLabelElement[];
4951
let groupInstance: MdButtonToggleGroup;
5052
let buttonToggleInstances: MdButtonToggle[];
5153
let testComponent: ButtonTogglesInsideButtonToggleGroup;
@@ -62,8 +64,13 @@ describe('MdButtonToggle', () => {
6264
groupInstance = groupDebugElement.injector.get(MdButtonToggleGroup);
6365

6466
buttonToggleDebugElements = fixture.debugElement.queryAll(By.directive(MdButtonToggle));
65-
buttonToggleNativeElements =
66-
buttonToggleDebugElements.map(debugEl => debugEl.nativeElement);
67+
68+
buttonToggleNativeElements = buttonToggleDebugElements
69+
.map(debugEl => debugEl.nativeElement);
70+
71+
buttonToggleLabelElements = fixture.debugElement.queryAll(By.css('label'))
72+
.map(debugEl => debugEl.nativeElement);
73+
6774
buttonToggleInstances = buttonToggleDebugElements.map(debugEl => debugEl.componentInstance);
6875
});
6976
}));
@@ -133,15 +140,19 @@ describe('MdButtonToggle', () => {
133140
let changeSpy = jasmine.createSpy('button-toggle change listener');
134141
buttonToggleInstances[0].change.subscribe(changeSpy);
135142

136-
buttonToggleInstances[0].checked = true;
143+
144+
buttonToggleLabelElements[0].click();
137145
fixture.detectChanges();
138146
tick();
139147
expect(changeSpy).toHaveBeenCalled();
140148

141-
buttonToggleInstances[0].checked = false;
149+
buttonToggleLabelElements[0].click();
142150
fixture.detectChanges();
143151
tick();
144-
expect(changeSpy).toHaveBeenCalledTimes(2);
152+
153+
// The default browser behavior is to not emit a change event, when the value was set
154+
// to false. That's why the change event was only triggered once.
155+
expect(changeSpy).toHaveBeenCalledTimes(1);
145156
}));
146157

147158
it('should emit a change event from the button toggle group', fakeAsync(() => {

src/components/button-toggle/button-toggle.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -303,10 +303,6 @@ export class MdButtonToggle implements OnInit {
303303
// Notify all button toggles with the same name (in the same group) to un-check.
304304
this.buttonToggleDispatcher.notify(this.id, this.name);
305305
}
306-
307-
if (newCheckedState != this._checked) {
308-
this._emitChangeEvent();
309-
}
310306
}
311307

312308
this._checked = newCheckedState;
@@ -368,6 +364,21 @@ export class MdButtonToggle implements OnInit {
368364
} else {
369365
this._toggle();
370366
}
367+
368+
// Emit a change event when the native input does.
369+
this._emitChangeEvent();
370+
}
371+
372+
_onInputClick(event: Event) {
373+
374+
// We have to stop propagation for click events on the visual hidden input element.
375+
// By default, when a user clicks on a label element, a generated click event will be
376+
// dispatched on the associated input element. Since we are using a label element as our
377+
// root container, the click event on the `slide-toggle` will be executed twice.
378+
// The real click event will bubble up, and the generated click event also tries to bubble up.
379+
// This will lead to multiple click events.
380+
// Preventing bubbling for the second event will solve that issue.
381+
event.stopPropagation();
371382
}
372383
}
373384

0 commit comments

Comments
 (0)