Skip to content

Commit b1f9dea

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

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
@@ -301,10 +301,6 @@ export class MdButtonToggle implements OnInit {
301301
// Notify all button toggles with the same name (in the same group) to un-check.
302302
this.buttonToggleDispatcher.notify(this.id, this.name);
303303
}
304-
305-
if (newCheckedState != this._checked) {
306-
this._emitChangeEvent();
307-
}
308304
}
309305

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

0 commit comments

Comments
 (0)