diff --git a/BREAKING.md b/BREAKING.md
index 7f16d41108..c95ba87190 100644
--- a/BREAKING.md
+++ b/BREAKING.md
@@ -192,6 +192,8 @@ Ionic now listens on the `keydown` event instead of the `keyup` event when deter
- Range no longer clamps assigned values within bounds. Developers will need to validate the value they are assigning to `ion-range` is within the `min` and `max` bounds when programmatically assigning a value.
+- The `name` property defaults to `ion-r-${rangeIds++}` where `rangeIds` is a number that is incremented for every instance of `ion-range`.
+
Searchbar
- `ionChange` is no longer emitted when the `value` of `ion-searchbar` is modified externally. `ionChange` is only emitted from user committed changes, such as typing in the searchbar and the searchbar losing focus.
diff --git a/core/api.txt b/core/api.txt
index 6f43a9fc1f..caeb8d2d93 100644
--- a/core/api.txt
+++ b/core/api.txt
@@ -1034,7 +1034,7 @@ ion-range,prop,legacy,boolean | undefined,undefined,false,false
ion-range,prop,max,number,100,false,false
ion-range,prop,min,number,0,false,false
ion-range,prop,mode,"ios" | "md",undefined,false,false
-ion-range,prop,name,string,'',false,false
+ion-range,prop,name,string,this.rangeId,false,false
ion-range,prop,pin,boolean,false,false,false
ion-range,prop,pinFormatter,(value: number) => string | number,(value: number): number => Math.round(value),false,false
ion-range,prop,snaps,boolean,false,false,false
diff --git a/core/src/components/range/range.tsx b/core/src/components/range/range.tsx
index c57982114e..1e24a85c6b 100644
--- a/core/src/components/range/range.tsx
+++ b/core/src/components/range/range.tsx
@@ -46,7 +46,7 @@ import type {
shadow: true,
})
export class Range implements ComponentInterface {
- private rangeId?: string;
+ private rangeId = `ion-r-${rangeIds++}`;
private didLoad = false;
private noUpdate = false;
private rect!: ClientRect;
@@ -91,12 +91,10 @@ export class Range implements ComponentInterface {
this.ionInput = debounce === undefined ? originalIonInput ?? ionInput : debounceEvent(ionInput, debounce);
}
- // TODO: In Ionic Framework v6 this should initialize to this.rangeId like the other form components do.
-
/**
* The name of the control, which is submitted with the form data.
*/
- @Prop() name = '';
+ @Prop() name = this.rangeId;
/**
* Show two knobs.
@@ -302,7 +300,9 @@ export class Range implements ComponentInterface {
* If user has custom ID set then we should
* not assign the default incrementing ID.
*/
- this.rangeId = this.el.hasAttribute('id') ? this.el.getAttribute('id')! : `ion-r-${rangeIds++}`;
+ if (this.el.hasAttribute('id')) {
+ this.rangeId = this.el.getAttribute('id')!;
+ }
this.inheritedAttributes = inheritAriaAttributes(this.el);
}
@@ -553,9 +553,9 @@ export class Range implements ComponentInterface {
private renderLegacyRange() {
if (!this.hasLoggedDeprecationWarning) {
printIonWarning(
- `Using ion-range with an ion-label has been deprecated. To migrate, remove the ion-label and pass your label directly into ion-toggle instead.
+ `Using ion-range with an ion-label has been deprecated. To migrate, remove the ion-label and pass your label directly into ion-range instead.
-Example: Volume:
+Example: Volume:
For ranges that do not have a visible label, developers should use "aria-label" so screen readers can announce the purpose of the range.
diff --git a/core/src/components/range/test/range.spec.ts b/core/src/components/range/test/range.spec.ts
index 4707cf5212..2898675c89 100644
--- a/core/src/components/range/test/range.spec.ts
+++ b/core/src/components/range/test/range.spec.ts
@@ -1,3 +1,4 @@
+import { newSpecPage } from '@stencil/core/testing';
import { Range } from '../range';
let sharedRange;
@@ -61,3 +62,17 @@ describe('Range', () => {
});
});
});
+
+describe('range id', () => {
+ it('should render custom id if passed', async () => {
+ const page = await newSpecPage({
+ components: [Range],
+ html: `
+ Range
+ `,
+ });
+
+ const range = page.body.querySelector('ion-range');
+ expect(range.getAttribute('id')).toBe('my-custom-range');
+ });
+});