I have a form in svelte, using shadcn-svelte, and zod.
Relevant code snippets:
// schema.ts
const formSchema = z.object({
/* ... */
maxParticipants: z.number()
});
<!-- form.svelte -->
<Form.Field {form} name="maxParticipants">
<Form.Control let:attrs>
<Form.Label>Max participants</Form.Label>
<Input {...attrs} type="number" bind:value={$formData.maxParticipants} />
</Form.Control>
<Form.FieldErrors />
</Form.Field>
Because inputs are strings, even though the input is set to type="number"
, it's a string, which means that when I try to submit, I get an error underneath the input (in the FieldErrors
, from the zod validation): "Expected number, received string".
I couldn't find a way to go about it, so all I have currently is just setting the input to type="text"
, and .string()
in the zod schema, and then in the actions, where I handle the form submission, cast it to a number, but that's would be very not optimal.
For input
elements of type="number"
Svelte will convert the value to a number when binding, but the type
has to be statically known, which is probably not the caes for this component (since the type is passed in here).
You could create a more specific NumberInput
which sets the type statically inside, then the value binding would yield number
or null
(if empty).
Alternatively, do not use a binding and use an event to get the value out.
Something like:
<Input
value={$formData.maxParticipants?.toString() ?? ''}
on:change={e => $formData.maxParticipants = parseInt(e.target.value)} />
(This is just for to illustrate the approach and does not handle everything properly, like the empty or white-space only cases.)