Skip to content

Commit 3d76173

Browse files
committed
feat: restore form-associated value state
Restore the element's value state after navigation or browser restart and support autofill. When the user agent updates a form-associated custom element's value on behalf of a user or as part of navigation, its `formStateRestoreCallback` is called, given the new state and a string indicating a reason, "autocomplete" or "restore", as arguments. https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/setFormValue
1 parent 94649be commit 3d76173

2 files changed

Lines changed: 24 additions & 1 deletion

File tree

src/range-slider-element.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,9 @@ export class RangeSliderElement extends HTMLElement {
193193
formResetCallback() {
194194
this.value = this.getAttribute('value') || this.#getDefaultValue();
195195
}
196+
formStateRestoreCallback(state) {
197+
this.value = state; // Restore slider position
198+
}
196199

197200
connectedCallback() {
198201
// Template setup
@@ -406,7 +409,7 @@ export class RangeSliderElement extends HTMLElement {
406409
if (oldValue !== newValue) {
407410
this.#value[index] = newValue;
408411
this.#valuePercent[index] = this.#getPercentFromValue(newValue);
409-
this.#internals.setFormValue(this.#value.join(','));
412+
this.#internals.setFormValue(this.value, this.value); // value, state
410413
this.#updateThumb(index, newValue);
411414
this.#updateTrackFill();
412415
for (const eventName of dispatchEvents) {

test/range-slider.test.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,26 @@ describe('range-slider', () => {
8080

8181
expect(element).toHaveValue('30');
8282
});
83+
84+
test('restores form state and does not dispatch events', async () => {
85+
const { element } = setup('<form><range-slider name="slider"></range-slider></form>');
86+
const { input, change } = listenToEvents(element, ['input', 'change']);
87+
const form = document.querySelector('form');
88+
89+
// Simulate browser session/BFCache restore (value, mode)
90+
element.formStateRestoreCallback('25', 'restore');
91+
expect(element).toHaveValue('25');
92+
expect(form).toHaveFormValues({ slider: '25' });
93+
94+
// Simulate browser autofill (value, mode)
95+
element.formStateRestoreCallback('70', 'autocomplete');
96+
expect(element).toHaveValue('70');
97+
expect(form).toHaveFormValues({ slider: '70' });
98+
99+
// Should not dispatch events (matches native input restore)
100+
expect(input).not.toHaveBeenCalled();
101+
expect(change).not.toHaveBeenCalled();
102+
});
83103
});
84104

85105
describe('attributes', () => {

0 commit comments

Comments
 (0)