Skip to content

Commit

Permalink
fix(material/slider): avoid error on some touchstart events (#23823)
Browse files Browse the repository at this point in the history
Fixes that the slider was throwing errors on some non-cancelable `touchstart` events.

Fixes #23820.

(cherry picked from commit 78db0d4)
  • Loading branch information
crisbeto authored and andrewseguin committed Jan 13, 2022
1 parent 81528bc commit 7be61b6
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 2 deletions.
14 changes: 13 additions & 1 deletion src/material/slider/slider.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ import {
dispatchKeyboardEvent,
dispatchMouseEvent,
createKeyboardEvent,
} from '../../cdk/testing/private';
createTouchEvent,
} from '@angular/cdk/testing/private';
import {Component, DebugElement, Type, ViewChild} from '@angular/core';
import {ComponentFixture, fakeAsync, flush, TestBed} from '@angular/core/testing';
import {FormControl, FormsModule, ReactiveFormsModule} from '@angular/forms';
Expand Down Expand Up @@ -242,6 +243,17 @@ describe('MatSlider', () => {
it('should have a focus indicator', () => {
expect(sliderNativeElement.classList.contains('mat-focus-indicator')).toBe(true);
});

it('should not try to preventDefault on a non-cancelable event', () => {
const event = createTouchEvent('touchstart');
const spy = spyOn(event, 'preventDefault');
Object.defineProperty(event, 'cancelable', {value: false});

dispatchEvent(sliderNativeElement, event);
fixture.detectChanges();

expect(spy).not.toHaveBeenCalled();
});
});

describe('disabled slider', () => {
Expand Down
8 changes: 7 additions & 1 deletion src/material/slider/slider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -672,14 +672,20 @@ export class MatSlider
const oldValue = this.value;
this._isSliding = 'pointer';
this._lastPointerEvent = event;
event.preventDefault();
this._focusHostElement();
this._onMouseenter(); // Simulate mouseenter in case this is a mobile device.
this._bindGlobalEvents(event);
this._focusHostElement();
this._updateValueFromPosition(pointerPosition);
this._valueOnSlideStart = oldValue;

// Despite the fact that we explicitly bind active events, in some cases the browser
// still dispatches non-cancelable events which cause this call to throw an error.
// There doesn't appear to be a good way of avoiding them. See #23820.
if (event.cancelable) {
event.preventDefault();
}

// Emit a change and input event if the value changed.
if (oldValue != this.value) {
this._emitInputEvent();
Expand Down

0 comments on commit 7be61b6

Please sign in to comment.