You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* add convert_formdata function
* WIP
* fix some types
* fix test
* fix
* fix test
* missed a spot
* simplify a bit
* add validation
* maybe this? the type stuff is too complicated for me
* get rid of dot/array notation, it adds too much complexity
* tighten up
* fix
* fix
* oops
* revert
* sort of working
* implement input/issues
* make input reactive
* enforce 1:1 relationship
* fix
* lint
* WIP
* WIP
* tidy up
* lint
* lint
* fix
* only enforce input parity
* use validation output, not input
* preflight should return instance
* DRY out
* implement preflight
* WIP validate method
* programmatic validation
* fix/tidy
* generate types
* docs
* add field(...) method
* more docs
* oops
* fix test
* fix docs
* Apply suggestions from code review
* guard against prototype pollution
* doc tweaks, fixes
* add valibot to playground
* changesets
* tell people about the breaking change
* remind ourselves to remove the warning
* fix changeset
* filter out files
* better file handling
* widen helper type to also catch unknown/the general type which will all result in infinite recursion type errors
* mentiond coercion
* only reset after a successful submission
* same for buttonProps
* typo
* redact sensitive info
* document underscore
* regenerate
* rename
* regenerate
* guard against array prototype pollution
---------
Co-authored-by: Ben McCann <[email protected]>
Co-authored-by: Simon Holthausen <[email protected]>
The `form` function makes it easy to write data to the server. It takes a callback that receives the current [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData)...
230
+
The `form` function makes it easy to write data to the server. It takes a callback that receives `data` constructed from the submitted [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData)...
The form object contains `method` and `action` properties that allow it to work without JavaScript (i.e. it submits data and reloads the page). It also has an `onsubmit` handler that progressively enhances the form when JavaScript is available, submitting data *without* reloading the entire page.
311
+
As with `query`, if the callback uses the submitted `data`, it should be [validated](#query-Query-arguments) by passing a [Standard Schema](https://standardschema.dev) as the first argument to `form`. The one difference is to `query` is that the schema inputs must all be of type `string` or `File`, since that's all the original `FormData` provides. You can however coerce the value into a different type — how to do that depends on the validation library you use.
The `name` attributes on the form controls must correspond to the properties of the schema — `title` and `content` in this case. If you schema contains objects, use object notation:
If you'd like type safety and autocomplete when setting `name` attributes, use the form object's `field` method:
359
+
360
+
```svelte
361
+
<label>
362
+
<h2>Title</h2>
363
+
<input name={+++createPost.field('title')+++} />
364
+
</label>
365
+
```
366
+
367
+
This will error during typechecking if `title` does not exist on your schema.
368
+
369
+
The form object contains `method` and `action` properties that allow it to work without JavaScript (i.e. it submits data and reloads the page). It also has an [attachment](/docs/svelte/@attach) that progressively enhances the form when JavaScript is available, submitting data *without* reloading the entire page.
370
+
371
+
### Validation
372
+
373
+
If the submitted data doesn't pass the schema, the callback will not run. Instead, the form object's `issues` object will be populated:
374
+
375
+
```svelte
376
+
<form {...createPost}>
377
+
<label>
378
+
<h2>Title</h2>
379
+
380
+
+++ {#ifcreatePost.issues.title}
381
+
{#each createPost.issues.title as issue}
382
+
<p class="issue">{issue.message}</p>
383
+
{/each}
384
+
{/if}+++
385
+
386
+
<input
387
+
name="title"
388
+
+++aria-invalid={!!createPost.issues.title}+++
389
+
/>
390
+
</label>
391
+
392
+
<label>
393
+
<h2>Write your post</h2>
394
+
395
+
+++ {#ifcreatePost.issues.content}
396
+
{#each createPost.issues.content as issue}
397
+
<p class="issue">{issue.message}</p>
398
+
{/each}
399
+
{/if}+++
400
+
401
+
<textarea
402
+
name="content"
403
+
+++aria-invalid={!!createPost.issues.content}+++
404
+
></textarea>
405
+
</label>
406
+
407
+
<button>Publish!</button>
408
+
</form>
409
+
```
410
+
411
+
You don't need to wait until the form is submitted to validate the data — you can call `validate()` programmatically, for example in an `oninput` callback (which will validate the data on every keystroke) or an `onchange` callback:
By default, issues will be ignored if they belong to form controls that haven't yet been interacted with. To validate _all_ inputs, call `validate({ includeUntouched:true })`.
420
+
421
+
For client-side validation, you can specify a _preflight_ schema which will populate `issues` and prevent data being sent to the server if the data doesn't validate:
422
+
423
+
```svelte
424
+
<script>
425
+
import*asvfrom'valibot';
426
+
import { createPost } from'../data.remote';
427
+
428
+
constschema=v.object({
429
+
title:v.pipe(v.string(), v.nonEmpty()),
430
+
content:v.pipe(v.string(), v.nonEmpty())
431
+
});
432
+
</script>
433
+
434
+
<h1>Create a newpost</h1>
435
+
436
+
<form {...+++createPost.preflight(schema)+++}>
437
+
<!---->
438
+
</form>
439
+
```
440
+
441
+
> [!NOTE] The preflight schema can be the same object as your server-side schema, if appropriate, though it won't be able to do server-side checks like 'this value already exists in the database'. Note that you cannot export a schema from a `.remote.ts` or `.remote.js` file, so the schema must either be exported from a shared module, or from a `<script module>` block in the component containing the `<form>`.
442
+
443
+
### Live inputs
444
+
445
+
The form object contains a `input` property which reflects its current value. As the user interacts with the form, `input` is automatically updated:
In the case of a non-progressively-enhanced form submission (i.e. where JavaScript is unavailable, for whatever reason) `input` is also populated if the submitted data is invalid, so that the user does not need to fill the entire form out from scratch.
461
+
462
+
You can prevent sensitive data (such as passwords and credit card numbers) from being sent back to the user by using a name with a leading underscore:
463
+
464
+
```svelte
465
+
<form {...register}>
466
+
<label>
467
+
Username
468
+
<input
469
+
name="username"
470
+
value={register.input.username}
471
+
aria-invalid={!!register.issues.username}
472
+
/>
473
+
</label>
474
+
475
+
<label>
476
+
Password
477
+
<input
478
+
type="password"
479
+
+++name="_password"+++
480
+
+++aria-invalid={!!register.issues._password}+++
481
+
/>
482
+
</label>
483
+
484
+
<button>Sign up!</button>
485
+
</form>
486
+
```
487
+
488
+
In this example, if the data does not validate, only the first `<input>` will be populated when the page reloads.
@@ -438,9 +624,7 @@ We can customize what happens when the form is submitted with the `enhance` meth
438
624
showToast('Oh no! Something went wrong');
439
625
}
440
626
})}>
441
-
<input name="title"/>
442
-
<textarea name="content"></textarea>
443
-
<button>publish</button>
627
+
<!---->
444
628
</form>
445
629
```
446
630
@@ -517,7 +701,7 @@ The `command` function, like `form`, allows you to write data to the server. Unl
517
701
518
702
> [!NOTE] Prefer `form` where possible, since it gracefully degrades if JavaScript is disabled or fails to load.
519
703
520
-
As with `query`, if the function accepts an argument, it should be [validated](#query-Query-arguments) by passing a [Standard Schema](https://standardschema.dev) as the first argument to `command`.
704
+
As with `query` and `form`, if the function accepts an argument, it should be [validated](#query-Query-arguments) by passing a [Standard Schema](https://standardschema.dev) as the first argument to `command`.
0 commit comments