I am trying to create a custom checkbox using Svelte and compile it to a custom element (with customElement: true) but I don't know what way is the proper way of using attributes.
Looking at the generated code it looks like the attributeChangedCallback and observedAttributes are generated automatically depending on what variables you export in the .svelte
file so that seems to work as expected though I haven't found any documentation for this.
Right now I have this hacky approach of creating the checked property manually and managing the different values of the checked attribute (to match native behavior) as seen here:
<script>
import { onMount } from 'svelte';
export let checked;
onMount(() => {
if (checked != null) {
checked = true;
} else {
checked = false;
}
});
</script>
I then simply set the checked attribute to the input element and add a change event to keep the property updated when checking/unchecking the input:
<input
on:change={(event) => {
checked = event.currentTarget.checked;
}}
type="checkbox"
{checked}
/>
Is this how you are meant to use attributes and managing property states with Svelte and custom elements?
While that works, Svelte allows you to simplify it quite a bit:
<svelte:options tag="my-checkbox"/>
<script>
// `checked` will be `false` by default, but a user may pass in a
// different value through the attribute/property with the same name.
export let checked = false;
// this next line isn't strictly necessary. if you want to guarantee
// `checked` is always a boolean even if the user passes a different
// value, you can use a reactive statement to consistently convert
// `checked` into a boolean. this will re-run automatically.
$: checked = (checked !== false);
</script>
<!--
`bind:checked` is a shorthand for `bind:checked={checked}`, which in
turn means the `checked` property of the input will have a two-way
binding to the `checked` property of this component. updating one will
automatically update the other.
-->
<input type="checkbox" bind:checked>
Svelte's reactivity system will ensure the component's checked
property/variable is kept in sync with the custom element's checked
property, and as you noted, changes to the custom element's attribute will also trigger an update to the component.
Do note that you won't see the changes in the component reflected in the element's attributes, so you'll have to do that manually if necessary. Usually the property access is enough, though.