Search code examples
sveltesvelte-3svelte-component

svelte each block grouping results delimma


I have an array called products that contains products. Each product belongs to a category.

 product = { category : "shorts", name : "whatever", ...}

Now when I iterate over that array in svelte, I use each block

{#each products as product}
 <li>
   {product.category} - {product.name}
</li>
{/each}

So my results are like this : shorts - blueshort shorts - greenshort shorts - yellowshort

My question is how to group the display the results by category. Like this

 shorts
          blueshort
          greenshort
          yellowshort
     hats 
          bluehat
          greenhat
          yellowwhatever

Is there a way to do it from the each block or I have to take care of it in the script and then send it to the html?

Is there a way to do that in the each block?


Solution

  • You can use reduce to group results by category and nested each statements:

    <script>
        let products = [
            { category : "shorts", name : "hat one" },
            { category : "shorts", name : "hat two" },
            { category : "hats", name : "hat one" },
            { category : "hats", name : "hat two" },
        ];
        
        // group products by category
        $: data = products.reduce((acc, curr) => {
            // create key and value of array if hasn't been created yet
            if (!acc[curr.category]) acc[curr.category] = [];
            acc[curr.category].push(curr.name);
            return acc;
        }, {});
    </script>
    
    <div>
        {#each Object.entries(data) as item}
        <div>{item[0]}</div>
        <ul>
            {#each item[1] as name}
                <li>{name}</li>
            {/each}
        </ul>
        {/each}
    </div>
    

    Here is an example in action

    Hopefully that helps.