2

I am trying to write an application where every 3 bookmarks, Svelte closes the Row and begins a new one, allowing for the rows to continue. I use sveltestrap components, and these are the "Row", "Col" and "Card*" tags seen.

<Row>
    {#each bookmarks as bookmark, i}
        <Col>
        <Card class="mb-3">
          <CardHeader>{bookmark.title}</CardHeader>
          <CardBody>
            <CardSubtitle>{#each Array(parseInt(bookmark.rating)) as _, i}
                <img fill="#ffffff" src="/res/star-fill.svg" alt="Star">
            {/each}{#each Array(5 - parseInt(bookmark.rating)) as _, i}
            <img src="/res/star.svg" alt="Star">
            {/each}
            </CardSubtitle>
            <CardText>{bookmark.description}</CardText>
          </CardBody>
          <CardFooter>{bookmark.rating}</CardFooter>
        </Card>
    </Col>
    
    {#if (i % 3 === 0)}
    </Row>
    <Row>
    {/if}
    {/each}
    </Row>
      

This gives me an error about closing an element that doesn't exist, but I'm trying to close the row before it. Is there any way for Svelte to see the previous element in its array?

apiary
  • 41
  • 4
  • What does `` do? Maybe you are better off using [CSS grid](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout). – Felix Kling Apr 07 '22 at 18:21

2 Answers2

3

One solution could be to cut the bookmarks in chunks of three, so you can wrap two #each loops - one for the rows and one for the columns with matching opening and closing tags.
Here's an example using a chunk function from this question >> REPL

<script>
    const items = [1,2,3,4,5,6,7,8,9,10]

    function chunkArray (arr, size) {
        return arr.length > size
            ? [arr.slice(0, size), ...chunkArray(arr.slice(size), size)]
        : [arr]
    }

    const groups = chunkArray(items, 3)
    console.log(groups)

</script>

{#each groups as items}
<div class="row">
    {#each items as item}
    <span class="column">{item}</span>
    {/each}
</div>
{/each}

Like commented I would question the Row component and think about if this is really neccessary or if there might be a css only solution instead...

Corrl
  • 6,206
  • 1
  • 10
  • 36
3
{#each Array(Math.ceil(bookmarks.length / 3)) as _, i}
    <Row>
        {#each bookmarks.slice(i * 3, i*3+3) as bookmark, j}
            <Col>
                <Card class="mb-3">
                    <CardHeader>{bookmark.title}</CardHeader>
                    <CardBody>
                        <CardSubtitle>
                            {#each Array(parseInt(bookmark.rating)) as _, k}
                                <img fill="#ffffff" src="/res/star-fill.svg" alt="Star">
                            {/each}
                            {#each Array(5 - parseInt(bookmark.rating)) as _, k}
                                <img src="/res/star.svg" alt="Star">
                            {/each}
                        </CardSubtitle>
                        <CardText>{bookmark.description}</CardText>
                    </CardBody>
                    <CardFooter>{bookmark.rating}</CardFooter>
                </Card>
            </Col>
        {/each}
    </Row>
{/each}
miwin
  • 1,160
  • 10
  • 12