Skip to content

fix(slide-toggle): drag not working in edge #8421

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 20, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions src/lib/slide-toggle/slide-toggle.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,29 @@ describe('MatSlideToggle without forms', () => {
.toBeFalsy('Expected the slide-toggle to not emit a change event.');
}));

it('should ignore clicks on the label element while dragging', fakeAsync(() => {
expect(slideToggle.checked).toBe(false);

gestureConfig.emitEventForElement('slidestart', slideThumbContainer);
gestureConfig.emitEventForElement('slide', slideThumbContainer, {
deltaX: 200 // Arbitrary, large delta that will be clamped to the end of the slide-toggle.
});
gestureConfig.emitEventForElement('slideend', slideThumbContainer);

expect(slideToggle.checked).toBe(true);

// Fake a change event that has been fired after dragging through the click on pointer
// release (noticeable on IE11, Edge)
inputElement.checked = false;
dispatchFakeEvent(inputElement, 'change');

// Flush the timeout for the slide ending.
tick();

expect(slideThumbContainer.classList).not.toContain('mat-dragging');
expect(slideToggle.checked).toBe(true);
}));

it('should update the checked property of the input', fakeAsync(() => {
expect(inputElement.checked).toBe(false);

Expand Down
33 changes: 16 additions & 17 deletions src/lib/slide-toggle/slide-toggle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,32 +161,31 @@ export class MatSlideToggle extends _MatSlideToggleMixinBase implements OnDestro
this._focusMonitor.stopMonitoring(this._inputElement.nativeElement);
}

/**
* This function will called if the underlying input changed its value through user interaction.
*/
/** Method being called whenever the underlying input emits a change event. */
_onChangeEvent(event: Event) {
// We always have to stop propagation on the change event.
// Otherwise the change event, from the input element, will bubble up and
// emit its event object to the component's `change` output.
event.stopPropagation();

// Sync the value from the underlying input element with the slide-toggle component.
// Releasing the pointer over the `<label>` element while dragging triggers another
// click event on the `<label>` element. This means that the checked state of the underlying
// input changed unintentionally and needs to be changed back.
if (this._slideRenderer.dragging) {
this._inputElement.nativeElement.checked = this.checked;
return;
}

// Sync the value from the underlying input element with the component instance.
this.checked = this._inputElement.nativeElement.checked;

// Emit our custom change event if the native input emitted one.
// It is important to only emit it, if the native input triggered one, because we don't want
// to trigger a change event, when the `checked` variable changes programmatically.
// Emit our custom change event only if the underlying input emitted one. This ensures that
// there is no change event, when the checked state changes programmatically.
this._emitChangeEvent();
}

/** Method being called whenever the slide-toggle has been clicked. */
_onInputClick(event: Event) {
// In some situations the user will release the mouse on the label element. The label element
// redirects the click to the underlying input element and will result in a value change.
// Prevent the default behavior if dragging, because the value will be set after drag.
if (this._slideRenderer.dragging) {
event.preventDefault();
}

// We have to stop propagation for click events on the visual hidden input element.
// By default, when a user clicks on a label element, a generated click event will be
// dispatched on the associated input element. Since we are using a label element as our
Expand Down Expand Up @@ -269,10 +268,10 @@ export class MatSlideToggle extends _MatSlideToggleMixinBase implements OnDestro

_onDragEnd() {
if (this._slideRenderer.dragging) {
let _previousChecked = this.checked;
this.checked = this._slideRenderer.dragPercentage > 50;
const newCheckedValue = this._slideRenderer.dragPercentage > 50;

if (_previousChecked !== this.checked) {
if (newCheckedValue !== this.checked) {
this.checked = newCheckedValue;
this._emitChangeEvent();
}

Expand Down