imagefocussvelteonfocussvelte-component

apply focus state to list of elements in svelte


I have a list of buttons below. When a focus event occurs on the button I need it to switch to the first logo, else it should show the second logo. What would I put in my ternary operator below to make this happen?

IMAGE MAP

import { Television_ChannelCode } from '@gql/schema';
import Logo1F from '@logos/Logo1F.svelte';
import Logo1U from '@logos/Logo1U.svelte';
import Logo2F from '@logos/Logo2F.svelte';
import Logo2U from '@logos/Logo2U.svelte';


const map = new Map<Television_ChannelCode, any>();
map.set(Television_ChannelCode.News, [Logo1F,Logo1U]);
map.set(Television_ChannelCode.Sports, [Logo2F, Logo2U]);

export const getLogoFromTelevisionChannelCode = (
    televisionChannelCode: Television_ChannelCode,
): any => {
    return map.get(televisionChannelCode);
};

CHOOSE IMAGE BASED ON FOCUS

import { getLogoFromTelevisionChannelCode } from '@lib/

{#each shows as show, index}
    <button on:focus={(ev) => console.log(ev)}>
            <div>
                <svelte:component this={getLogoFromTelevisionChannelCode(
                            show.channel.channelCode)[(--HERE-- ? 0 : 1)]}
                />
            </div>
    </button>
{/each}

Solution

  • It's not as simple as that. You need additional state to track the focus and since you are in a loop there are several options:

    The primary logic is always the same, update the item focus state in the focus event handler, then use it in the expression that selects the image.

    If you want to switch back on blur, then you can simplify this, as you can only ever have one focused item, which can easily be tracked in a single state variable (e.g. using the index). You then just have to compare that against the each index.

    Here is simplified example of tracking the focus for a single item:

    <script>
        let items = ['a', 'b', 'c'];
    
        let focused = null;
    </script>
    
    {#each items as item, index}
        <div>
            <button on:focus={() => focused = index}
                    on:blur={() => focused = focused == index ? null : focused}>
                {item}
                {#if focused == index}
                    [Focused]
                {/if}
            </button>
        </div>
    {/each}