sveltekit-superforms icon indicating copy to clipboard operation
sveltekit-superforms copied to clipboard

Validation is not triggered with `oninput` and `value` props in Svelte 5

Open rayrw opened this issue 1 year ago • 4 comments

  • [x] Before posting an issue, read the FAQ and search the previous issues.

Description

While it does work when using bind:value in an input tag, validation is not triggered when manually mutating the value via an oninput handler (oninput={e => $form.field = e.currentTarget.value }).

If applicable, a MRE

I've made a minimal reproduction repo. When inputting values in text fields with oninput + value props, the validation is not triggered, but it works when using the text fields with bind:value.

https://sveltelab.dev/github.com/rayrw/svelte5-superforms-proxy-field (right click to open in a new tab)

rayrw avatar Oct 28 '24 07:10 rayrw

Since the validation is triggered on blur the first time, you need an extra event handler for validating it manually. Something like:

onblur={() => validate('email')}

(validate is available on the superForm object)

ciscoheat avatar Nov 15 '24 12:11 ciscoheat

Thank you for answering! I looked into this again and found that when using on:input, it works as expected for my use case, and I wondered why. It turns out that there seems to be a race condition when it is with oninput.

When it's with oninput, the input event listener registered here get called before the Form store's setter function which sets the tainted state and the paths to NextChange. This affects the comparison inside the focusout event listener. However, when it's with on:input, the opposite happened. The Form store and NextChange get updated before the input event listener which then makes the focusout event listener correctly compare between NextChange_paths() and lastInputChange.

Sorry I'm not quite sure how to explain this. As a workaround, I would go for using oninputcapture instead of oninput for now, as it makes the order same as on:input.

<input
	value={$form.email}
-	oninput={(e) => {
+	oninputcapture={(e) => {
		$form.email = e.currentTarget.value;
	}}
/>

rayrw avatar Aug 14 '25 07:08 rayrw

Thank you, will have to check what can be done about this. But oninputcapture, isn't that React?

ciscoheat avatar Aug 16 '25 05:08 ciscoheat

Thank you, will have to check what can be done about this. But oninputcapture, isn't that React?

It it a svelte 5 event handler. https://svelte.dev/tutorial/svelte/capturing

bigmac44 avatar Oct 23 '25 05:10 bigmac44