diff --git a/core/src/components/range/range.tsx b/core/src/components/range/range.tsx index da4c2d7534..830e185a5e 100644 --- a/core/src/components/range/range.tsx +++ b/core/src/components/range/range.tsx @@ -2,7 +2,7 @@ import type { ComponentInterface, EventEmitter } from '@stencil/core'; import { Component, Element, Event, Host, Prop, State, Watch, h } from '@stencil/core'; import { findClosestIonContent, disableContentScrollY, resetContentScrollY } from '@utils/content'; import type { Attributes } from '@utils/helpers'; -import { inheritAriaAttributes, clamp, debounceEvent, renderHiddenInput } from '@utils/helpers'; +import { inheritAriaAttributes, clamp, debounceEvent, renderHiddenInput, isSafeNumber } from '@utils/helpers'; import { printIonWarning } from '@utils/logging'; import { isRTL } from '@utils/rtl'; import { createColorClasses, hostContext } from '@utils/theme'; @@ -109,7 +109,11 @@ export class Range implements ComponentInterface { */ @Prop() min = 0; @Watch('min') - protected minChanged() { + protected minChanged(newValue: number) { + if (!isSafeNumber(newValue)) { + this.min = 0; + } + if (!this.noUpdate) { this.updateRatio(); } @@ -120,7 +124,11 @@ export class Range implements ComponentInterface { */ @Prop() max = 100; @Watch('max') - protected maxChanged() { + protected maxChanged(newValue: number) { + if (!isSafeNumber(newValue)) { + this.max = 100; + } + if (!this.noUpdate) { this.updateRatio(); } @@ -300,6 +308,10 @@ export class Range implements ComponentInterface { } this.inheritedAttributes = inheritAriaAttributes(this.el); + // If the min or max is not safe, set it to 0 or 100 respectively. + // Our watch does this, but not before the initial load. + this.min = isSafeNumber(this.min) ? this.min : 0; + this.max = isSafeNumber(this.max) ? this.max : 100; } componentDidLoad() { diff --git a/core/src/components/range/test/range.spec.ts b/core/src/components/range/test/range.spec.ts index 8698f9bbf0..557d09814d 100644 --- a/core/src/components/range/test/range.spec.ts +++ b/core/src/components/range/test/range.spec.ts @@ -28,6 +28,23 @@ describe('Range', () => { }); }); + it('should handle undefined min and max values by falling back to defaults', async () => { + const page = await newSpecPage({ + components: [Range], + html: ` +
Range
+
`, + }); + + const range = page.body.querySelector('ion-range')!; + // Here we have to cast this to any, but in its react wrapper it accepts undefined as a valid value + range.min = undefined as any; + range.max = undefined as any; + await page.waitForChanges(); + expect(range.min).toBe(0); + expect(range.max).toBe(100); + }); + it('should return the clamped value for a range dual knob component', () => { sharedRange.min = 0; sharedRange.max = 100;