feat: allow to run preflight validation only - #14744
Conversation
That way you can e.g. run preflight on each keystroke and full validation only on blur
🦋 Changeset detectedLatest commit: 7368c91 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
| /** Set this to `true` to also show validation issues of fields that haven't been touched yet. */ | ||
| includeUntouched?: boolean; | ||
| /** Set this to `true` to only run the `preflight` validation. */ | ||
| clientOnly?: boolean; |
There was a problem hiding this comment.
maybe this, so it's explicitly linked to .preflight(...)?
| clientOnly?: boolean; | |
| preflightOnly?: boolean; |
|
What would this look like in practice? <script>
import { form } from "$lib/remote/forms.remote.ts";
import { schema } from "$lib/schema";
function validate() {
form.preflight(schema).validate({ preflightOnly: true }); // runs preflight schema
form.validate(); // runs server schema
}
</script>
<form {...form}></form>or <script>
import { form } from "$lib/remote/forms.remote.ts";
import { schema } from "$lib/schema";
function validate() {
form.validate(); // runs preflight schema
form.validate({ preflightOnly: false }); // skips preflight, runs server schema
}
</script>
<form {...form.preflight(schema)}></form> |
|
The preflight schema would always be used. This just allows you to skip server validation. So you could for example do preflight validation on every keystroke, but additionally run server validation on <form
{...myform.preflight(schema)}
oninput={() => myform.validate({ preflightOnly: true })}
onchange={() => myform.validate()}
>...</form> |
|
One thing I don't love about this is that server issues get nuked as soon as preflight-only validation succeeds. We can fix that with a simple change... -const is_server_validation = !validated?.issues;
+const is_server_validation = !validated?.issues && !preflightOnly;...but then we have another problem: preflight validation issues will be added to server validation issues, instead of replacing them, and it looks really weird. Fixing that is slightly trickier. I've opened #14759 to address it. |
|
I don't sure I understand - I do want to have the server validation issues persisted when a preflight validation fails. Why wouldn't I? There's no world in which a server validation can be duplicate to a preflight validation, because then the server validation wouldn't have ran in the first place. Having a server validation issue ripped out under my fingers while typing is never a good thing IMO. And IIRC we agreed that we don't want to have them go away, so the simple fix should be enough? |
|
Consider a case similar to the one in the test case I added in #14759 — on the server you have this schema... v.object({
a: v.pipe(v.string(), v.minLength(3, 'a is too short'), v.maxLength(7, 'a is too long')),
b: v.pipe(v.string(), v.minLength(3, 'b is too short')),
c: v.pipe(v.string(), v.minLength(3, 'c is too short'))
})...and on the client you have this: v.object({
a: v.pipe(v.string(), v.maxLength(7, 'a is too long')),
b: v.string(),
c: v.string()
})This is contrived, but totally valid — the preflight constraints are a subset of the server-side constraints. If you submit this with empty inputs, preflight validation will succeed and you'll be left with the following: Currently on this branch, as soon as you start typing into the
|
* preserve server issues on preflight validation, unless there are newer preflight-only issues * sort correctly * no longer necessary * lint * Update packages/kit/src/runtime/client/remote-functions/form.svelte.js Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com> --------- Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
* feat: allow to run preflight validation only That way you can e.g. run preflight on each keystroke and full validation only on blur * clientOnly -> preflightOnly * Preserve server issues when doing preflight-only validation (sveltejs#14759) * preserve server issues on preflight validation, unless there are newer preflight-only issues * sort correctly * no longer necessary * lint * Update packages/kit/src/runtime/client/remote-functions/form.svelte.js Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com> --------- Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com> --------- Co-authored-by: Rich Harris <rich.harris@vercel.com> Co-authored-by: Rich Harris <richard.a.harris@gmail.com>
`merge_with_server_issues` runs whenever preflight validation produces issues, which with the documented `oninput` pattern means on every keystroke while a form has issues. Merging costs O(S·C + M·K·log M) for S server issues, C client issues, M merged issues and K form keys. 🤓 This change drops it to O(S + C + K + M·log M). 🤓 N fields with N issues (half server, half client), Node 22 x64, median of repeated runs: | fields | before | after | speedup | | ---: | ---: | ---: | ---: | | 400 | 1.6 ms | 0.1 ms | 15× | | 800 | 7.9 ms | 0.3 ms | 27× | | 1600 | 33.0 ms | 0.8 ms | 42× | | 3200 | 163.8 ms | 2.2 ms | 76× | Small forms are at parity or slightly faster, since the old code already allocated the key array. Output is unchanged: identical issue-object ordering to the previous implementation across 10,000 randomized cases covering duplicated form keys, duplicated issue names, names absent from the form, mixed server and client issues and empty collections. The merge semantics negotiated in #14744/#14759 are preserved. --- ### Before submitting the PR, please make sure you do the following - [ ] It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs - [x] This message body should clearly illustrate what problems it solves. - [ ] Ideally, include a test that fails without this PR but passes with it. ### Tests - [x] Run the tests with `pnpm test` and lint the project with `pnpm lint` and `pnpm check` ### Changesets - [x] If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running `pnpm changeset` and following the prompts. Changesets that add features should be `minor` and those that fix bugs should be `patch`. Please prefix changeset messages with `feat:`, `fix:`, or `chore:`.
That way you can e.g. run preflight on each keystroke and full validation only on blur
Please don't delete this checklist! Before submitting the PR, please make sure you do the following:
Tests
pnpm testand lint the project withpnpm lintandpnpm checkChangesets
pnpm changesetand following the prompts. Changesets that add features should beminorand those that fix bugs should bepatch. Please prefix changeset messages withfeat:,fix:, orchore:.