Svelte: Associate label and input in a reusabe way
Asked Answered
G

2

6

I'm building a Svelte input component which should be usable multible times on the same page.

<div>
    <label>{label}</label>
    <div>
        <input bind:value>
        <!-- some more elements -->
    </div>
</div>

Trying to associate label and input I have the following problem:

  • I can't use implicit association by changing the outer <div> to <label>, since the input is not a direct child.
  • I can't use the labels for attribute, since reusing the element would create mutible identical ids.

Is there a way to create component instance unique ids (pre- or postfixed) in Svelte or is there another solution to this problem.


Or is the best solution to manually set a random string as id?

<script>
    const id = random_string();
    /* ... */
</script>

<div>
    <label for={id}>{label}</label>
    <div>
        <input {id} bind:value>
        <!-- some more elements -->
    </div>
</div>
Goody answered 20/11, 2020 at 10:41 Comment(0)
Q
17

You could define a counter in module context and then use it to create unique IDs

Input.svelte

<script context="module">
    let counter = 0
</script>
<script>
        export let label
        let value
        let eltId = 'input_'+ counter++
</script>

<div>
    <label for={eltId}>{label}</label>
    <div>
        <input id={eltId} bind:value>
    </div>
</div>    

App.svelte

<script>
    import Input from './Input.svelte'
</script>

<Input label='Select Country' />
<Input label='Select Country' />
<Input label='Select Country' />

See REPL

Quorum answered 26/1, 2021 at 17:23 Comment(0)
S
1

Why not just define a unique name for the input since your need one? You could then just have a component like:

Input.svelte

<script>
    export let name
    export let label
    let value
        
    const getInputId = () => {
        return `input_${name}`
    }
</script>

<div>
    <label for={getInputId()}>{label}</label>
    <div>
        <input id={getInputId()} bind:value>
    </div>
</div>

And use it like:

App.svelte

<script>
    import Input from './Input.svelte'
</script>

<Input name='country' label='Select Country' />

Checkout the REPL.

Staunch answered 20/11, 2020 at 11:20 Comment(2)
This is not possible, if the top form itself has to be reusable. And why should the compnent need a name?Goody
This is a footgun, you're gonna accidentally collide two names and then clicking some label will toggle a checkbox on the other side of the pageSiphonostele

© 2022 - 2024 — McMap. All rights reserved.