From 00c18007596660d85272e72cb36168ffa13a3d4e Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Sat, 16 Mar 2024 21:37:33 +0100 Subject: [PATCH] slightly different approach --- .../client/dom/elements/bindings/input.js | 7 +++-- .../client/dom/elements/bindings/select.js | 3 +- .../client/dom/elements/bindings/shared.js | 29 +++++++++++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/packages/svelte/src/internal/client/dom/elements/bindings/input.js b/packages/svelte/src/internal/client/dom/elements/bindings/input.js index fcf56b7e89..cd52230c0e 100644 --- a/packages/svelte/src/internal/client/dom/elements/bindings/input.js +++ b/packages/svelte/src/internal/client/dom/elements/bindings/input.js @@ -1,6 +1,7 @@ import { DEV } from 'esm-env'; import { render_effect } from '../../../reactivity/effects.js'; import { stringify } from '../../../render.js'; +import { listen_to_event_and_reset_event } from './shared.js'; /** * @param {HTMLInputElement} input @@ -9,7 +10,7 @@ import { stringify } from '../../../render.js'; * @returns {void} */ export function bind_value(input, get_value, update) { - input.addEventListener('input', () => { + listen_to_event_and_reset_event(input, 'input', () => { if (DEV && input.type === 'checkbox') { throw new Error( 'Using bind:value together with a checkbox input is not allowed. Use bind:checked instead' @@ -72,7 +73,7 @@ export function bind_group(inputs, group_index, input, get_value, update) { binding_group.push(input); - input.addEventListener('change', () => { + listen_to_event_and_reset_event(input, 'change', () => { // @ts-ignore var value = input.__value; @@ -114,7 +115,7 @@ export function bind_group(inputs, group_index, input, get_value, update) { * @returns {void} */ export function bind_checked(input, get_value, update) { - input.addEventListener('change', () => { + listen_to_event_and_reset_event(input, 'change', () => { var value = input.checked; update(value); }); diff --git a/packages/svelte/src/internal/client/dom/elements/bindings/select.js b/packages/svelte/src/internal/client/dom/elements/bindings/select.js index 5e6241f8cd..09fe6e9b7e 100644 --- a/packages/svelte/src/internal/client/dom/elements/bindings/select.js +++ b/packages/svelte/src/internal/client/dom/elements/bindings/select.js @@ -1,4 +1,5 @@ import { effect } from '../../../reactivity/effects.js'; +import { listen_to_event_and_reset_event } from './shared.js'; /** * Selects the correct option(s) (depending on whether this is a multiple select) @@ -58,7 +59,7 @@ export function selected(option) { export function bind_select_value(select, get_value, update) { var mounting = true; - select.addEventListener('change', () => { + listen_to_event_and_reset_event(select, 'change', () => { /** @type {unknown} */ var value; diff --git a/packages/svelte/src/internal/client/dom/elements/bindings/shared.js b/packages/svelte/src/internal/client/dom/elements/bindings/shared.js index 379ce82f1e..4b0c351669 100644 --- a/packages/svelte/src/internal/client/dom/elements/bindings/shared.js +++ b/packages/svelte/src/internal/client/dom/elements/bindings/shared.js @@ -25,3 +25,32 @@ export function listen(target, events, handler, call_handler_immediately = true) }; }); } + +let listening_to_form_reset = false; + +/** + * Listen to the given event, and then instantiate a global form reset listener if not already done, + * to notify all bindings when the form is reset + * @param {HTMLElement} element + * @param {string} event + * @param {() => void} handler + */ +export function listen_to_event_and_reset_event(element, event, handler) { + element.addEventListener(event, handler); + // @ts-expect-error + element.__on_reset = handler; + + if (!listening_to_form_reset) { + listening_to_form_reset = true; + document.addEventListener('reset', (evt) => { + requestAnimationFrame(() => { + if (!evt.defaultPrevented) { + for (const e of /**@type {HTMLFormElement} */ (evt.target).elements) { + // @ts-expect-error + e.__on_reset?.(); + } + } + }); + }); + } +}