Repita o elemento HTML várias vezes usando ngFor com base em um número

Como eu uso o *ngFor para repetir um elemento HTML várias vezes?

Por exemplo: Se eu tenho uma variável de membro atribuída a 20. Como eu uso a diretiva * ngFor para fazer uma repetição div 20 vezes?

Você poderia usar o seguinte:

 @Component({ (...) template: ` 
` }) export class SomeComponent { Arr = Array; //Array type captured in a variable num:number = 20; }

Ou implemente um pipe personalizado:

 import {PipeTransform, Pipe} from '@angular/core'; @Pipe({ name: 'fill' }) export class FillPipe implements PipeTransform { transform(value) { return (new Array(value)).fill(1); } } @Component({ (...) template: ` 
`, pipes: [ FillPipe ] }) export class SomeComponent { arr:Array; num:number = 20; }

Existem dois problemas com as soluções recomendadas usando Arrays :

  1. É um desperdício. Em particular para números grandes.
  2. Você tem que defini-los em algum lugar que resulte em muita confusão para uma operação tão simples e comum.

Parece mais eficiente definir um Pipe (uma vez), retornando um Iterable :

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

Exemplo de uso (renderizando uma grade com largura / altura dinâmicas):

 
{{ x }}
{{ y }}

Você pode fazer isso simples no seu HTML:

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

E use a variável “number” para indexar.

 

Substitua 20 por sua variável

Uma solução mais simples e reutilizável talvez para usar diretivas estruturais personalizadas como essa.

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

E usá-lo assim:

  

Abordagem mais simples:

Defina um helperArray e instancie-o dinamicamente (ou estático, se desejar) com o comprimento da contagem que você deseja criar seus elementos HTML. Por exemplo, eu quero obter alguns dados do servidor e criar elementos com o comprimento da matriz que é retornada.

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

Em seguida, use o helperArray no meu modelo HTML.

 

Aqui está uma versão ligeiramente melhorada da diretiva estrutural de Ilyass Lamrani, que permite que você use o índice em seu modelo:

 @Directive({ selector: '[appRepeatOf]' }) export class RepeatDirective { constructor(private templateRef: TemplateRef, 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); } } } 

Uso:

 
  • Index: {{i}}
  • Se você estiver usando o Lodash , você pode fazer o seguinte:

    Importe o Lodash para o seu componente.

     import * as _ from "lodash"; 

    Declare uma variável de membro dentro do componente para fazer referência ao Lodash.

     lodash = _; 

    Então, na sua opinião, você pode usar a function de intervalo . 20 pode ser substituído por qualquer variável no seu componente.

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

    Deve ser dito que a binding a funções na visão pode ser cara, dependendo da complexidade da function que você está chamando como Detecção de Mudança irá chamar a function repetidamente.