Reputation: 305
I want to generate a list of custom components , composed of an input field and a few checkboxes:
<script>
const messages = [
{ id: "2fzae4", text: "aaaaa"},
{ id: "456ndr", text: "bbbbb"}
];
const tags = [
{ id: "01", label: "Twitter"},
{ id: "02", label: "Instagram"}
];
</script>
<ul>
{#each messages as msg (msg.id)}
<li>
<Ainput textField={msg.text} {tags}/>
</li>
{/each}
</ul>
// This is a part of the <Ainput> component
<div class="wrapper">
<input type="text" bind:value={textField}/>
<Tag {tags} />
</div>
// Tag component, a set of checkboxes
<script>
export let tags;
</script>
<div>
{#each tags as tag (tag.id)}
<div>
<checkbox id="{tags.id}"/>
<label for="{tags.id}">{tags.label}</label>
</div>
{/each}
</div>
I need to pass down unique tag.id values in the array 'tags' on every iteration to make checkboxes work, but how to achieve this?
Upvotes: 1
Views: 5299
Reputation: 311
You don't need a unique id necessarily if you are looping through an array of objects.
{#each messages as msg (msg)}
Each object is already unique.
Upvotes: 0
Reputation: 29012
In many cases, you don't need to do that. Check out this answer here. You can just put the <input>
inside the <label>
, then no id
/for
is needed:
<div>
{#each tags as tag (tag.id)}
<div>
<label>
<input type="checkbox"/>
{tags.label}
</label>
</div>
{/each}
</div>
Working demo:
<div>
<label>
<input type="checkbox">
Click me, please!
</label>
</div>
<div>
<label>
<input type="checkbox">
No, click me instead!
</label>
</div>
However, as pointed out by commenters below, this isn't always a perfect solution. Instead, if you really want to use such IDs, you could generate them on the fly as follows:
<script>
// ...
const ids = new WeakMap()
function getId (key) {
if (!ids.has(key)) ids.set(key, crypto.randomUUID())
return ids.get(key)
}
</script>
<!-- ... and then somewhere in your code: -->
{#each tags as tag (tag.id)} <!-- If you want, you can use getId(tag) here too -->
{@const id = getId(tag)}
<div>
<input type="checkbox" {id} />
<label for={id}>{tags.label}</label>
</div>
{/each}
This will produce unique IDs every time and will not leak the assigned IDs even in case the input array changes (as long as the array has objects and not primitive values) due to the usage of a WeakMap
as opposed to a regular Map
.
Upvotes: 0