Repeat HTML element several times using ngFor based on number

How to use *ngFor to repeat an HTML element multiple times?

For example: If I have a member variable assigned to 20. How do I use the * ngFor directive to make a repeat of the div 20 times?

+62
angular
Apr 10 '16 at 21:13
source share
10 answers

You can use the following:

 @Component({ (...) template: ' <div *ngFor="let i of Arr(num).fill(1)"></div> ' }) export class SomeComponent { Arr = Array; //Array type captured in a variable num:number = 20; } 

Or implement a custom pipe:

 import {PipeTransform, Pipe} from '@angular/core'; @Pipe({ name: 'fill' }) export class FillPipe implements PipeTransform { transform(value) { return (new Array(value)).fill(1); } } @Component({ (...) template: ' <div *ngFor="let i of num | fill"></div> ', pipes: [ FillPipe ] }) export class SomeComponent { arr:Array; num:number = 20; } 
+64
Apr 10 '16 at 21:22
source share

There are two problems with recommended solutions using Arrays :

  1. It is wasteful. In particular for large quantities.
  2. You have to identify them somewhere, which leads to a lot of mess for such a simple and common operation.

It seems more efficient to define a Pipe (once) by returning Iterable :

 import {PipeTransform, Pipe} from '@angular/core'; @Pipe({name: 'times'}) export class TimesPipe implements PipeTransform { transform(value: number): any { const iterable = <Iterable<any>> {}; iterable[Symbol.iterator] = function* () { let n = 0; while (n < value) { yield ++n; } }; return iterable; } } 

Usage example (mesh rendering with dynamic width / height):

 <table> <thead> <tr> <th *ngFor="let x of colCount|times">{{ x }}</th> </tr> </thead> <tbody> <tr *ngFor="let y of rowCount|times"> <th scope="row">{{ y }}</th> <td *ngFor="let x of colCount|times"> <input type="checkbox" checked> </td> </tr> </tbody> </table> 
+29
Sep 04 '17 at 10:05
source share
 <div *ngFor="let dummy of ' '.repeat(20).split(''), let x = index"> 

Replace 20 your variable

+29
Jan 29 '18 at 2:30
source share

You can simply do this in your HTML:

 *ngFor="let number of [0,1,2,3,4,5...,18,19]" 

And use the variable "number" for indexing.

+17
Mar 15 '17 at 6:12
source share

A simpler and more reusable solution, perhaps to use a custom structured directive like this.

 import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core'; @Directive({ selector: '[appTimes]' }) export class AppTimesDirective { constructor( private templateRef: TemplateRef<any>, private viewContainer: ViewContainerRef) { } @Input() set appTimes(times: number) { for (let i = 0 ; i < times ; i++) { this.viewContainer.createEmbeddedView(this.templateRef); } } } 

And use it as follows:

 <span *appTimes="3" class="fa fa-star"></span> 
+9
Nov 24 '17 at 2:04 on
source share
 <ng-container *ngFor="let i of [].constructor(20)">🐱</ng-container> 

generates 🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱

+2
Jan 17 '19 at 8:32
source share

If you use Lodash , you can do the following:

Import Lodash into your component.

 import * as _ from "lodash"; 

Declare a member variable in the component to reference Lodash.

 lodash = _; 

Then, in your opinion, you can use the range function . 20, you can replace any variable in your component.

 *ngFor="let number of lodash.range(20)" 

I must say that binding to functions in a view can be expensive, depending on the complexity of the function that you are calling, since Change Detection will call the function again.

+1
Jun 19 '18 at 7:54
source share

Simplified Approach:

Define helperArray and program it dynamically (or statically, if you want) with the length of the count you want your HTML elements to create. For example, I want to get some data from the server and create elements with the length of the returned array.

 export class AppComponent { helperArray: Array<any>; constructor(private ss: StatusService) { } ngOnInit(): void { this.ss.getStatusData().subscribe((status: Status[]) => { this.helperArray = new Array(status.length); }); } } 

Then use helperArray in my HTML template.

 <div class="content-container" *ngFor="let i of helperArray"> <general-information></general-information> <textfields></textfields> </div> 
0
Jul 14 '17 at 16:19
source share

Here is a slightly improved version of the Ilyass Lamrani structural directive that allows you to use the index in your template:

 @Directive({ selector: '[appRepeatOf]' }) export class RepeatDirective { constructor(private templateRef: TemplateRef<any>, private viewContainer: ViewContainerRef) { } @Input() set appRepeatOf(times: number) { const initialLength = this.viewContainer.length; const diff = times - initialLength; if (diff > 0) { for (let i = initialLength; i < initialLength + diff; i++) { this.viewContainer.createEmbeddedView(this.templateRef, { $implicit: i }); } } else { for (let i = initialLength - 1; i >= initialLength + diff ; i--) { this.viewContainer.remove(i); } } } 

Using:

 <li *appRepeat="let i of myNumberProperty"> Index: {{i}} </li> 
0
May 03 '18 at 14:14
source share

The most efficient and concise way to achieve this is to add an iterator utility. Do not bother with values. Don't worry about setting a variable in the ngFor directive:

 function times(max: number) { return { [Symbol.iterator]: function* () { for (let i = 0; i < max; i++, yield) { } } }; } @Component({ template: ''' <ng-template ngFor [ngForOf]="times(6)"> repeats 6 times! </ng-template> ''' }) export class MyComponent { times = times; } 
0
Dec 27 '18 at 10:37
source share



All Articles