Svelte: Associate label and input in a reusabe way

Viewed 1786

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>
2 Answers

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

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.

Related