JHeth
JHeth

Reputation: 8366

Svelte 3 - How to loop each block X amount of times

I'm hoping to find a way to iterate over an #each block a set amount of times in Svelte 3. In Vue I would do something like this:

<li v-for="i in 3"><!-- somecontent --></li>

But as I understand Svelte handles loops much differently using the .length property of the array being #eached. Is there some way to pull off something like this in Svelte?

{#each 3 as i}
  <li><!-- somecontent --></li>
{/if}

Upvotes: 90

Views: 64687

Answers (6)

Antony Jones
Antony Jones

Reputation: 3180

An #each tag can loop anything with a length property, so:

{#each {length: 3} as _, i}
    <li>{i + 1}</li>
{/each}

will also work, if you prefer.

Also since Svelte 5 you can drop the as

{#each { length: 8 }, rank}
    <div>{rank}</div>
{/each}

Upvotes: 198

Jon Musselwhite
Jon Musselwhite

Reputation: 1821

I'm just going to throw this method out there for anyone who would like to consider an alternative to arrays...

ES6 Generators

Generators are supported by over 97% of browsers globally, according to Can I Use. Instead of creating an Array, we can define a generator function that yields the given number of times.

Javascript:

function* range(start, end) {
  for (let i = start; i < end; i++) yield i;
}

... or Typescript:

function* range(start: number, end: number): Generator<number> {
  for (let i = start; i < end; i++) yield i;
}

Then use it in your Svelte block:

{#each range(1, 3) as i}
    <li><!-- --></li>
{/each}

The usage is identical to the method described in @Dmitry-Kokhanevich's answer, so I just copied the Svelte code block from theirs for this example.

Obviously, you might want to adjust the comparison operator to be <= instead of < if you want to include the end number, or reverse the operation entirely if you are using the numbers and want to count down instead of up. This method allows for a lot of flexibility.

For example, you can simplify it's usage slightly if you just want to use it to repeat a loop a certain number of times without caring what the index number actually is:

function* repeat(count: number): Generator<number> {
  for (let i = 0; i < count; i++) yield i;
}

Then, use it like this:

{#each repeat(4) as i}
  <li><!-- --></li>
{/each}

I think that makes the code a little more self-documenting and it is extremely close to the syntax requested by the original asker.

Upvotes: 2

Dmitry Kokhanevich
Dmitry Kokhanevich

Reputation: 11

You can also do it with helper:

/* code */
export function range(from, to) {
    const result = [];
    let i = from;

    while (i <= to) {
        result.push(i);
        i += 1;
    }

    return result;
}
<!-- template -->
{#each range(1, 3) as i}
    <li><!-- --></li>
{/each}

Upvotes: 1

MaxWall
MaxWall

Reputation: 205

You can use clean variable from the script section (mmm... for a pagination):

// script
export let numOfPages = 10
const pagesArray = Array.from({length: numOfPages}, (x, i) => i+1) // [1,2,3,4,5,6,7,8,9,10]

// template
{#each pagesArray as page}
    <li>{page}</li>
{/each}

Upvotes: 1

sk shahriar ahmed raka
sk shahriar ahmed raka

Reputation: 1179

i Use like this for travelling from a to b in Svelte

{#each Array.from(Array(b+1).keys()).slice(a) as i }
    <h1>{i}</h1>                    
{/each}

example (1 to 100):

{#each Array.from(Array(100+1).keys()).slice(1) as i }
    <h1>{i}</h1>                    
{/each}

Upvotes: 3

CD..
CD..

Reputation: 74146

You can use {#each ...}, like:

{#each Array(3) as _, i}
    <li>{i + 1}</li>
{/each}

Upvotes: 131

Related Questions