Ripeti più volte l’elemento HTML usando ngFor in base a un numero

Come si usa *ngFor ripetere più volte un elemento HTML?

Ad es .: se ho una variabile membro assegnata a 20. Come uso la direttiva * ngFor per fare una ripetizione 20 volte?

Potresti usare quanto segue:

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

Oppure implementa un pipe personalizzato:

 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; }

Ci sono due problemi con le soluzioni consigliate usando gli Arrays :

  1. È uno spreco. In particolare per grandi numeri.
  2. Devi definirli da qualche parte che si traduce in un sacco di confusione per un’operazione così semplice e comune.

Sembra più efficiente definire un Pipe (una volta), restituendo un 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; } } 

Esempio di utilizzo (rendering di una griglia con larghezza / altezza dynamic):

 
{{ x }}
{{ y }}

Puoi farlo semplicemente nel tuo codice HTML:

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

E usa la variabile “numero” per indicizzare.

 

Sostituisci 20 con la tua variabile

Una soluzione più semplice e riutilizzabile potrebbe utilizzare una direttiva strutturale personalizzata come questa.

 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 usalo in questo modo:

  

Approccio più semplice:

Definisci un helperArray e istanzialo dynamicmente (o statico se vuoi) con la lunghezza del conteggio che vuoi creare i tuoi elementi HTML. Ad esempio, voglio ottenere alcuni dati dal server e creare elementi con la lunghezza dell’array restituito.

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

Quindi utilizzare helperArray nel mio modello HTML.

 

Ecco una versione leggermente migliorata della direttiva strutturale di Ilyass Lamrani che consente di utilizzare l’indice nel modello:

 @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 stai usando Lodash , puoi fare quanto segue:

    Importa Lodash nel tuo componente.

     import * as _ from "lodash"; 

    Dichiarare una variabile membro all’interno del componente per fare riferimento a Lodash.

     lodash = _; 

    Quindi, a tuo avviso, puoi utilizzare la funzione intervallo . 20 può essere sostituito da qualsiasi variabile nel componente.

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

    Va detto che il binding a funzioni nella vista potrebbe essere costoso, a seconda della complessità della funzione che si sta chiamando, poiché Change Detection chiamerà ripetutamente la funzione.