Reputation: 655
I have a svelte component like this:
<script lang="ts">
import { faBarsStaggered } from '@fortawesome/free-solid-svg-icons';
import { onMount } from 'svelte';
import Fa from 'svelte-fa/src/fa.svelte';
let navbarItemsWrapper: HTMLUListElement;
let showDrawer = false;
onMount(() => {
navbarItemsWrapper.querySelectorAll('a').forEach((element) => {
element.addEventListener('click', () => {
showDrawer = false;
});
});
});
</script>
<div class="drawer">
<input id="navbar-drawer" type="checkbox" class="drawer-toggle" bind:checked={showDrawer} />
<div class="drawer-content flex flex-col">
<!-- Navbar -->
<div class="w-full navbar">
<div class="flex-none lg:hidden">
<label for="navbar-drawer" class="btn btn-square btn-ghost">
<Fa icon={faBarsStaggered} />
</label>
</div>
</div>
</div>
<div class="drawer-side z-10">
<label for="navbar-drawer" class="drawer-overlay" />
<ul class="menu p-4 w-80 h-full bg-base-200" bind:this={navbarItemsWrapper}>
<slot name="drawer-items" />
</ul>
</div>
</div>
As you can see, I'm updating the showDrawer
variable when a user clicks on a link. But this wont update the checkbox checked state. But if I bind the checked
attribute of input to showDrawer
instead like this:
<input id="navbar-drawer" type="checkbox" class="drawer-toggle" bind:checked={showDrawer} />
everything works like a charm. Using bind:[name]={variable}
is for two-way data binding which is not something that I need here. So why do I need have to use it for this to work?
---- EDIT: To get more infomation about how svelte reactivity system works let me add more questions about this topic:
on:click
. Because if that was the case the reactivity system would understand that it needs to update the showDrawer
on the checkboxshowDrawer
variable?Upvotes: 0
Views: 194
Reputation: 185180
This should just work. As soon as any local state is modified, it will be invalidated if used reactively (e.g. in markup). Hard to know what the real issue is without a minimal, completely contained example.
As for what happens when using on:click
: It has no bearing on reactivity at all.
The primary difference is, that it is just cleaner:
The approach you have taken here is really not good. You claim that "the parent should not care how the drawer is closed" yet the parent has to know that a
elements need to be passed in, for any of this to work. And the drawer attaches events to elements it does not own.
There are various better ways of doing this. E.g.
on:click
on an ancestor of the <slot>
and just let the event bubble up.<Drawer let:close>
<a href="..." on:click|preventDefault={close}>Item</a>
</Drawer>
<slot close={() => showDrawer = false} />
Upvotes: 1