I have a parent component (List
) which displays a list of child components (Block
). Nested blocks have a button that allows the user to add/remove them to the selection.
The List component also contains a table were are listed all the selected Blocks: the user can unselect a Block there too.
My problem is that when unselected from the table#selection
, the isSelected
variable is obviously not updated
How can I dynamically update the isSelected
variable inside the Block component? Am I handling the logic wrong?
List.svelte
<script>
import Block from './Block.svelte';
export let blocks = [];
let selection = {};
let isBlockSelected = (block) => selection.hasOwnProperty(block.id);
function removeFromSelection(blockId) {
const { [blockId]: _, ...rest } = selection;
selection = rest;
// 🛑 TODO make block aware that it has been unselected
}
function addToSelection(block) {
selection = { ...selection, [block.id]: block };
}
function handleToggleSelection(event) {
const { block } = event.detail;
if (!isBlockSelected(block)) {
addToSelection(block);
} else {
removeFromSelection(block.id);
}
}
</script>
<div>
{#each blocks as block (block.id)}
<Block {block} on:toggleSelection={handleToggleSelection} isSelected={isBlockSelected(block)}/>
{/each}
</div>
<table id="selection">
<tbody>
{#each Object.entries(selection) as [id, meta]}
<tr>
<td>
<a href="/page/{id}" target="_blank">{meta.title}</a>
<button class="delete" aria-label="close" on:click={() => removeFromSelection(id)}></button>
</td>
</tr>
{/each}
</tbody>
</table>
Block.svelte
<script>
import {createEventDispatcher} from "svelte";
export let block;
export let isSelected = false;
const dispatch = createEventDispatcher();
function toggleSelection(block) {
dispatch('toggleSelection', { block });
isSelected = !isSelected
}
</script>
<div>
{block.title}
<button on:click={() => toggleSelection(block)}>
{#if isSelected}
Remove from selection
{:else}
Add to selection
{/if}
</button>
</div>
To make
isBlockSelected(block)
update when selection
changes either add it as a parameter to the declaration and all calls
const isBlockSelected = (block, selection) => selection.hasOwnProperty(block.id);
or make the statement reactive
$: isBlockSelected = (block) => selection.hasOwnProperty(block.id);