Why isn't bind:value
allowed on checkboxes?
In Svelte, if you try to bind the value of a checkbox input, you get an error. Why is this? If I remember correctly, a checkbox's values are either "on" or its original value. I know this wouldn't be used often (if at all) but why is Svelte so strict about checkbox values being bound that there's an error code dedicated to it?
It's a common mistake to try to bind value
rather than checked
.
There is generally also no point in binding it because the checkbox does not change it on user interaction.
Is there a reason why it gives an error instead of just a compiler warning?
My guess is that it would not work as intended at all.
Bindings on DOM elements are usually associated with an event, e.g. is the value
binding on text boxes based on the input
event. If this was not set up for checkboxes, an error may make more sense.
Warnings are usually used if something might not behave quite as intended, often there is also a chance of false positives and in the case of accessibility warnings the functionality might only be partial (e.g. not properly supporting screen readers).
is there a way to dynamically add bindings depending on input type?
Input component i would like to use, excerpt, ideally the binds would only be added if the type property matches, eg something like:
<script module lang="ts">
type Props = {
type?: 'checkbox' | 'text' | 'file'
value?: string | number | null
checked?: boolean | null
files?: File[] | null
}
</script>
<script lang="ts">
const {
type,
value: $bindable(),
checked: $bindable(),
files: $bindable(),
} = $props()
</script>
<input
bind:value={type !== 'file' && type !== 'checkbox' ? value : null}
bind:checked={type === 'checkbox' ? value : null}
bind:files={type === 'file' ? value : null}
/>
edit:
it's obvious to me why this does not work, is there a way to make it though?
bind={type === 'file' ? {files} : null}
does not work either.
For the bindings, you probably could use function binding syntax.
The Props
type should be defined as a union on the object level, otherwise the various property types will be disconnected from their type
value.
type Props =
| { type: 'text', value?: string, /* ... */ }
| { type: 'checkbox', checked?: boolean, /* ... */ }
| /* ... */;
(Also, this should have just been a separate question.)