Repetir el elemento HTML varias veces usando ngFor basado en un número


¿Cómo uso *ngFor para repetir un elemento HTML varias veces?

Para eg: Si tengo una variable miembro asignada a 20. ¿Cómo uso la directiva * ngFor para repetir un div 20 veces?

 59
Author: takeradi, 2016-04-11

8 answers

Podrías usar lo siguiente:

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

O implementar una tubería personalizada:

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;
}
 58
Author: Thierry Templier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-06 15:28:38

Hay dos problemas con las soluciones recomendadas usando Arrays:

  1. Es un desperdicio. En particular para grandes números.
  2. Tienes que definirlos en algún lugar que resulta en un montón de desorden para una operación tan simple y común.

Parece más eficiente definir un Pipe (una vez), devolviendo 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;
  }
}

Ejemplo de uso (renderizando una cuadrícula con ancho / alto dinámico):

<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>
 22
Author: Andreas Baumgart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-04 10:50:05
<div *ngFor="let dummy of ' '.repeat(20).split(''), let x = index">

Reemplace 20 con su variable

 21
Author: Aximili,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-29 02:30:09

Puede hacer esto en su HTML:

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

Y utilice la variable "number" para indexar.

 18
Author: Dekonunes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-15 06:12:04

Una solución más simple y reutilizable tal vez usar una directiva estructural personalizada como esta.

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

}

Y úsalo así:

<span *appTimes="3" class="fa fa-star"></span>
 8
Author: Ilyass Lamrani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-24 14:04:35

Un enfoque más sencillo:

Defina un helperArray e instancielo dinámicamente (o estático si lo desea) con la longitud del recuento que desea crear sus elementos HTML. Por ejemplo, quiero obtener algunos datos del servidor y crear elementos con la longitud de la matriz que se devuelve.

export class AppComponent {
  helperArray: Array<any>;

  constructor(private ss: StatusService) {
  }

  ngOnInit(): void {
    this.ss.getStatusData().subscribe((status: Status[]) => {
      this.helperArray = new Array(status.length);
    });
  }
}

Entonces usa el helperArray en mi plantilla HTML.

<div class="content-container" *ngFor="let i of helperArray">
  <general-information></general-information>
  <textfields></textfields>
</div>
 0
Author: Florian Leitgeb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-14 16:19:01

Aquí hay una versión ligeramente mejorada de la directiva estructural de Ilyass Lamrani que le permite usar el índice en su plantilla:

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

}

Uso:

<li *appRepeat="let i of myNumberProperty">
    Index: {{i}}
</li>
 0
Author: MK10,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-03 14:36:13

Si está utilizando Lodash , puede hacer lo siguiente:

Import Lodash en el componente.

import * as _ from "lodash";

Declare una variable miembro dentro del componente para hacer referencia a Lodash.

lodash = _;

Luego, en su vista, puede usar la función de rango . 20 puede ser reemplazado por cualquier variable en su componente.

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

Debe decirse que el enlace a funciones en la vista puede ser costoso, dependiendo de la complejidad de la función que está llamando como La detección de cambios llamará a la función repetidamente.

 0
Author: Davy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-19 07:54:31