I've come unstuck while building my first Svelte project. I've built a tree-view component in which each node has a checkbox; checkbox-change values should be passed down to the child nodes.
My tree-view consists of two components (TreeNode
is a class which contains, for example the text which should appear on each node):
<!-- TreeView.svelte -->
<script lang="ts">
import TreeNode from "./TreeNode";
import TreeNodeView from "./TreeNodeView.svelte";
export let isChecked: boolean = false;
export let treeNodes: Array<TreeNode>;
</script>
<ul role="group">
{#each treeNodes as treeNode ( treeNode.id )}
<TreeNodeView {isChecked} {treeNode} />
{/each}
</ul>
<!-- TreeNodeView.svelte -->
<script lang="ts">
import ...
let hasFocus: boolean = false;
function onChecked(e: CustomEvent<boolean>) {
isChecked = e.detail;
}
export let isChecked: boolean;
export let treeNode: TreeNode;
$:{
console.log(`${treeNode.text}.isChecked = ${isChecked}`);
}
</script>
<li>
</div>
{:else}
<div> </div>
{/if}
{#if treeNode.children.length === 0}
<Link href="~"><Checkbox labelText={treeNode.text} /></Link>
{:else}
<Checkbox checked={isChecked} labelText={treeNode.text} id={treeNode.id} name={treeNode.id} on:check={onChecked} />
{/if}
{#if treeNode.isSelected && treeNode.children.length}
<TreeView treeNodes={treeNode.children} {isChecked} />
{/if}
</li>
In the reactive block ($: { ... }
) it appears that the isChecked
value is being passed down, but none of the checkboxes reflect the updated value. I.e., when checking de-CH
in the following node...
I see this in the console...
... but the two child-node checkboxes remain stubbornly unchecked.
What have I missed?
[The styled components I'm using are carbon-components-svelte.]
UPDATE:
I realised that I had omitted the checked
binding in one of the checkboxes: In my TreeNodeView.svelte component I needed to add...
{#if treeNode.children.length === 0}
<Link href="~">
<Checkbox labelText={treeNode.text} checked={isChecked} /> // << checked={isChecked}
</Link>
{:else}
// ...
{/if}
What a silly mistake - sorry to anyone who gave this any thought.
If the change is not being reflected in the UI, it could be due to the way the checkbox component is handling its
checked
prop. If the checkbox component is not properly reacting to changes in it'schecked
prop, it might not update its internal state or the DOM correctly, even though the prop itself is being updated.This way is to ensure that the checkbox component updates correctly when it's
checked
prop changes. It is the use of two-way binding. You can use thebind:checked
directive to create a two-way binding between thechecked
prop and the checkbox's internal state. This means that changes to the checkbox's state will update thechecked
prop, and changes to thechecked
prop will update the checkbox's state.Example two-way binding for this;
This should ensure that the checkbox's state is updated whenever the
isChecked
prop changes, and vice versa.If still problem with the above, It could be that the checkbox component is not properly handling the
on:check
event. You could try using Svelte's built-inon:change
event instead, which is triggered whenever the checkbox's state changes. You could then update theisChecked
prop in the event handler.Example;
This will ensure that the
isChecked
prop is updated whenever the checkbox's state changes, which should cause the component to re-render with the updated state.Edit (As additional issue found.)
In your
TreeNodeView.svelte
component, you're using aCustomEvent
to update theisChecked
value. However, this event is only being listened to in theTreeNodeView
component itself, and not being passed up to the parentTreeView
component or any child components. This means that when you check a box, theisChecked
value is updated in theTreeNodeView
component, but this change isn't reflected in the parent or child components.If so, you'll need to dispatch an event from the
TreeNodeView
component whenever the checkbox is clicked, and listen for this event in the parentTreeView
component. When the event is fired, the parent component should update theisChecked
value for the correspondingTreeNode
and pass this new value down to the child components.In
TreeNodeView.svelte
, dispatch an event, so whenever a checkbox is clicked, theisChecked
value should be updated in the parentTreeView
component and passed down to the child components, updating the state of the checkboxes accordingly.