Second instance of a component uses the function set on the first instance in svelte

57 views Asked by At

I have created a component that I want to use to select a player. There can be two different players, and I was trying to have each one call a different function.

However, when I select an option on either component, is always calls the selectP1 function.

App.svelte :

<script lang="ts">
    import SwapIcon from '~icons/tabler/arrows-diff';
    import PlayerSelector from '../components/PlayerSelector.svelte';
    import type { AutocompleteOption } from '@skeletonlabs/skeleton';

    function selectP1(e: CustomEvent<AutocompleteOption>): void {
        console.log('P1 is ' + e.detail.value);
    }

    function selectP2(e: CustomEvent<AutocompleteOption>): void {
        console.log('P2 is ' + e.detail.value);
    }
</script>

<div class="container h-1/5 w-3/4 mx-auto flex justify-between items-center">
    <PlayerSelector on:selection={(e) => selectP1(e)} />
    <button type="button" class="btn-icon variant-filled-primary"><SwapIcon /></button>
    <PlayerSelector on:selection={(e) => selectP2(e)} />
</div>

PlayerSelector.svelte :

<script lang="ts">
    import {
        Autocomplete,
        type AutocompleteOption,
        type PopupSettings
    } from '@skeletonlabs/skeleton';
    import { popup } from '@skeletonlabs/skeleton';

    let popupSettings: PopupSettings = {
        event: 'focus-click',
        target: 'popupAutocomplete',
        placement: 'bottom'
    };

    let player: string = '';

    const players: AutocompleteOption[] = [
        { label: 'John Smith', value: 'JSmith' },
        { label: 'Tom Smith', value: 'TSmith' },
        { label: 'Joe Jones', value: 'JJones' }
    ];
</script>

<div class="card w-3/4 max-w-sm max-h-48 p-4 overflow-y-auto">
    <input
        class="input autocomplete p-1"
        type="search"
        name="autocomplete-search"
        bind:value={player}
        placeholder="Search..."
        use:popup={popupSettings}
    />
    <div data-popup="popupAutocomplete">
        <Autocomplete bind:input={player} options={playerList} on:selection />
    </div>
</div>

Regardless of which PlayerSelector I update, it always calls selectP1. I can't figure out how to make this work as expected.

I got the Autocomplete setup from https://www.skeleton.dev/components/autocomplete

1

There are 1 answers

1
brunnerh On BEST ANSWER

The problem is that the names are not unique, so both popups target the same element.

Would recommend exporting a name property and using that for the input and the popup.

export let name: string;
let popupSettings = {
    event: 'focus-click',
    target: name + 'popupAutocomplete',
    placement: 'bottom'
};
<input {name} ...>

<div data-popup="{name}popupAutocomplete">

(Changing input name might be optional, but it would help differentiate the values if sent to the server via a form.)