Search code examples
javascriptsveltesvelte-3sveltekit

How can I use a reactive function inside a class attribute in Svelte?


How can I set an elements class attribute based on the return value of a function in svelte?

I am trying to make a speed typing game with svelte. I need to display the currently typed letters in different colors based on their state (inactive/active/right/wrong).

I have a function that gets the state of a typed letter from the array sentenceState where x is the words index and y is a letters index.

function getLetterStyle(x, y) {
  const state = sentenceState[x][y];
  switch (state) {
    case null:
      return '';
    case 0:
      return 'text-black border-l border-black';
    case 1:
    case 2:
      return 'text-green-500';
    case -1:
      return 'text-red-500';
  }
}

The sentenceState is a reactive array of arrays where each value is either null, 0, 1, 2 or -1. Based on these values I want to dynamically change the class attribute of an element. I tried to use this function like this:

{#each activeSentence as word, wordIndex}
    {#each word as letter, letterIndex}
      <span class={getLetterStyle(wordIndex, letterIndex)>{letter}</span>
    {/each}
{/each}

This does not seem to work the way I would have imagined. It works on the initial page load. But when sentenceState updates, the class does not change accordingly.

getLetterStyle() will only be called once. Is there a way to use a function with parameters for the class attribute? What am I doing wrong here?

Thanks in advance!

Edit: here is a REPL https://svelte.dev/repl/4b02dd3eacee43748e05de3071e59f0b?version=3.42.2


Solution

  • There's nothing making your #each loop reactive.

    The #each loop is generating elements based on sentence, but this variable never gets updated, so it never re-renders.

    One solution here is to instead calculate your styles per-letter reactively and then letting the #each generate elements based on that.

    Working REPL: https://svelte.dev/repl/77977b39b8964c8ba32acb063ceeb407?version=3.42.2