From 5162563f20d9b59b6164b9a51aa27911996b616f Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Sat, 23 Oct 2021 10:42:56 +0200 Subject: [PATCH] fix(material/slider): avoid error on some touchstart events Fixes that the slider was throwing errors on some non-cancelable `touchstart` events. Fixes #23820. --- src/material/slider/slider.spec.ts | 14 +++++++++++++- src/material/slider/slider.ts | 8 +++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/material/slider/slider.spec.ts b/src/material/slider/slider.spec.ts index a9acb3be6232..e0ba9dfee109 100644 --- a/src/material/slider/slider.spec.ts +++ b/src/material/slider/slider.spec.ts @@ -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'; @@ -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', () => { diff --git a/src/material/slider/slider.ts b/src/material/slider/slider.ts index 1c7e547c00f3..174128c1634d 100644 --- a/src/material/slider/slider.ts +++ b/src/material/slider/slider.ts @@ -672,7 +672,6 @@ 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); @@ -680,6 +679,13 @@ export class MatSlider 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();