I try to use checkboxs with SuperForm (and formFieldProxy
).
And i have some problems:
- i don't understand why i have no way (or don't find the one) to retrieve checkbox value instead of the checked boolean (native html checkbox send input value, the value is just conditioned by the checked state)
- when i try to use
bind:group
i retrieve checkboxs values but all are stored as array
My reservation Zod schema
const ReservationObject = z.object({
id: z.string().uuid(),
reservation_id: z.string(),
denomination: z.string(),
price: z.coerce.number(),
options: z.array(
z.object({
id: z.string().uuid(),
optionDenomination: z.string(),
price: z.coerce.number()
})
),
total: z.number().optional(),
isBooked: z.boolean()
});
const ReservationsObject = z.object({
reservation_id: z.string(),
isSuspended: z.boolean(),
booking: z.array(ReservationObject)
});
The schema used for form values
export const BuyingReservation = z.object({
buying: z.array(
z.object({
buyReservation: z.string().uuid(),
buyReservationOption: z.array(z.string().uuid())
})
)
});
SuperForm object
const defaultBuyingEntry = [{ buyReservation: '', buyReservationOption: [] }];
const buying: BuyingReservation = { buying: defaultBuyingEntry };
const superform = superForm(buying, {
dataType: 'json',
resetForm: false,
invalidateAll: false
});
const { form, submitting, enhance } = superform;
The form
<form method="POST" use:enhance action="/" class={styles['form']}>
{#each booking.booking as item, index}
<div class={styles['booking__row']}>
<p class={styles['booking__row-denomination']}>
{item.denomination} : <span>{item.price}€</span>
<Input
{superform}
id={`${index}-buyReservation`}
field="buying[{index}].buyReservation"
type="checkbox"
label={'Réserver'}
value={item.id}
grouped={true}
/>
</p>
<div class={styles['booking__row-options']}>
{#each item.options as option, optionIndex}
<div class={styles['booking__row-option']}>
<p class={styles['booking__row-options-denomination']}>
{option.optionDenomination} : <span>{option.price}€</span>
</p>
<Input
{superform}
id={`${index}-${optionIndex}-buyReservationOption`}
field="buying[{index}].buyReservationOption[{optionIndex}]"
type="checkbox"
label={'Ajouter'}
value={option.id}
grouped={true}
/>
</div>
{/each}
</div>
</div>
{/each}
<input
type="submit"
class={styles['form__field-static']}
value="Reserver et payer"
disabled={$submitting}
/>
</form>
My reusable input
let { label, className, field, superform, grouped, ...others }: Props = $props();
const { value, errors, constraints } =
!!field && !!superform ? formFieldProxy(superform, field) : {};
<input
{...others}
name={field}
data-invalid={$errors}
aria-invalid={$errors ? 'true' : undefined}
class={[styles['input'], className].join(' ')}
{...$constraints}
type="checkbox"
bind:group={$value} // or bind:checked={$value}
/>
The results: if bind:checked
{
"buying": [
{
"buyReservation": true,
"buyReservationOption": [
true,
false
]
},
]
}
if bind:group
{
"buying": [
{
"buyReservation": [
"61ee077d-9db9-4286-bd57-25d5ab0fe27e"
],
"buyReservationOption": [
[
"6b2fe441-96eb-46fe-aa2b-fe78319d27fc"
],
[
"0fa3b2ab-e2bc-4407-8827-7de6a8f7fb06"
]
]
}
]
}
I try to use checkboxs with SuperForm (and formFieldProxy
).
And i have some problems:
- i don't understand why i have no way (or don't find the one) to retrieve checkbox value instead of the checked boolean (native html checkbox send input value, the value is just conditioned by the checked state)
- when i try to use
bind:group
i retrieve checkboxs values but all are stored as array
My reservation Zod schema
const ReservationObject = z.object({
id: z.string().uuid(),
reservation_id: z.string(),
denomination: z.string(),
price: z.coerce.number(),
options: z.array(
z.object({
id: z.string().uuid(),
optionDenomination: z.string(),
price: z.coerce.number()
})
),
total: z.number().optional(),
isBooked: z.boolean()
});
const ReservationsObject = z.object({
reservation_id: z.string(),
isSuspended: z.boolean(),
booking: z.array(ReservationObject)
});
The schema used for form values
export const BuyingReservation = z.object({
buying: z.array(
z.object({
buyReservation: z.string().uuid(),
buyReservationOption: z.array(z.string().uuid())
})
)
});
SuperForm object
const defaultBuyingEntry = [{ buyReservation: '', buyReservationOption: [] }];
const buying: BuyingReservation = { buying: defaultBuyingEntry };
const superform = superForm(buying, {
dataType: 'json',
resetForm: false,
invalidateAll: false
});
const { form, submitting, enhance } = superform;
The form
<form method="POST" use:enhance action="/" class={styles['form']}>
{#each booking.booking as item, index}
<div class={styles['booking__row']}>
<p class={styles['booking__row-denomination']}>
{item.denomination} : <span>{item.price}€</span>
<Input
{superform}
id={`${index}-buyReservation`}
field="buying[{index}].buyReservation"
type="checkbox"
label={'Réserver'}
value={item.id}
grouped={true}
/>
</p>
<div class={styles['booking__row-options']}>
{#each item.options as option, optionIndex}
<div class={styles['booking__row-option']}>
<p class={styles['booking__row-options-denomination']}>
{option.optionDenomination} : <span>{option.price}€</span>
</p>
<Input
{superform}
id={`${index}-${optionIndex}-buyReservationOption`}
field="buying[{index}].buyReservationOption[{optionIndex}]"
type="checkbox"
label={'Ajouter'}
value={option.id}
grouped={true}
/>
</div>
{/each}
</div>
</div>
{/each}
<input
type="submit"
class={styles['form__field-static']}
value="Reserver et payer"
disabled={$submitting}
/>
</form>
My reusable input
let { label, className, field, superform, grouped, ...others }: Props = $props();
const { value, errors, constraints } =
!!field && !!superform ? formFieldProxy(superform, field) : {};
<input
{...others}
name={field}
data-invalid={$errors}
aria-invalid={$errors ? 'true' : undefined}
class={[styles['input'], className].join(' ')}
{...$constraints}
type="checkbox"
bind:group={$value} // or bind:checked={$value}
/>
The results: if bind:checked
{
"buying": [
{
"buyReservation": true,
"buyReservationOption": [
true,
false
]
},
]
}
if bind:group
{
"buying": [
{
"buyReservation": [
"61ee077d-9db9-4286-bd57-25d5ab0fe27e"
],
"buyReservationOption": [
[
"6b2fe441-96eb-46fe-aa2b-fe78319d27fc"
],
[
"0fa3b2ab-e2bc-4407-8827-7de6a8f7fb06"
]
]
}
]
}
Share
Improve this question
asked Mar 2 at 22:49
GeioGeio
9719 bronze badges
1 Answer
Reset to default 0i don't understand why i have no way (or don't find the one) to retrieve checkbox value instead of the checked boolean (native html checkbox send input value, the value is just conditioned by the checked state)
The browser does that when submitting a form:
value
Thevalue
attribute is one which all<input>
s share; however, it serves a special purpose for inputs of typecheckbox
: when a form is submitted, only checkboxes which are currently checked are submitted to the server, and the reported value is the value of thevalue
attribute. If thevalue
is not otherwise specified, it is the stringon
by default
However when you're on the client side, no form submission happens, and the value
attribute is just an attribute, that's present regardless of the checked
state, see the "Clicky" button:
function doThing() {
for (const cb of document.querySelectorAll("input[type=checkbox]"))
console.log(cb.value, cb.checked);
}
function doFilter() {
console.log(JSON.stringify(
[...document.querySelectorAll("input[type=checkbox]")]
.filter(cb => cb.checked)
.map(cb => cb.value)));
}
<input type="checkbox" value="hello">hello <input type="checkbox" value="world" checked>world<br>
<button onclick="doThing()">Clicky</button><br><button onclick="doFilter()">Filter</button>
While there's a chance that svelte
supports what you want, with vanilla JS you have to combine the two attributes yourself, as the "Filter" button shows.