¿Cómo utilizo *ngForpara repetir un elemento HTML varias veces?
Por ejemplo: si tengo una variable miembro asignada a 20. ¿Cómo uso la directiva * ngFor para hacer que un div se repita 20 veces?
¿Cómo utilizo *ngForpara repetir un elemento HTML varias veces?
Por ejemplo: si tengo una variable miembro asignada a 20. ¿Cómo uso la directiva * ngFor para hacer que un div se repita 20 veces?
Respuestas:
Puedes 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;
}
arr=Array;?
<div *ngFor="let dummy of ' '.repeat(20).split(''), let x = index">
Reemplazar 20con su variable
<ng-container *ngFor="let i of [].constructor(20)">🐱</ng-container>
genera 🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱
Hay dos problemas con las soluciones recomendadas que utilizan Arrays:
Parece más eficiente definir a 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<any>> {};
iterable[Symbol.iterator] = function* () {
let n = 0;
while (n < value) {
yield ++n;
}
};
return iterable;
}
}
Ejemplo de uso (renderizado de 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>
Puede hacer esto en su HTML:
*ngFor="let number of [0,1,2,3,4,5...,18,19]"
Y use la variable "número" para indexar.
20a una variable miembro .. así que esto no ayudará mucho
*ngFor="let number of [0,1,2,3,4,5...,199,200]":-D
Una solución más simple y reutilizable tal vez sea 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 utilícelo así:
<span *appTimes="3" class="fa fa-star"></span>
La forma más eficiente y concisa de lograr esto es agregando una utilidad de iterador. No se moleste en ceder valores. No se moleste en establecer una variable en la directiva ngFor:
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;
}
Si está utilizando Lodash , puede hacer lo siguiente:
Importe Lodash a su componente.
import * as _ from "lodash";
Declare una variable miembro dentro del componente para hacer referencia a Lodash.
lodash = _;
Luego, en su opinión, 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 la vinculación a funciones en la vista puede ser costosa, dependiendo de la complejidad de la función que está llamando, ya que Change Detection llamará a la función repetidamente.
No necesita completar la matriz como se sugiere en la mayoría de las respuestas. Si usa index en su ngForbucle, todo lo que necesita crear es una matriz vacía con la longitud correcta:
const elements = Array(n); // n = 20 in your case
y en tu opinión:
<li *ngFor="let element in elements; let i = index">
<span>{{ i }}</span>
</li>
Enfoque más simple:
Defina un helperArray y ejecútelo dinámicamente (o estático si lo desea) con la longitud del recuento que desea para 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);
});
}
}
Luego use helperArray en mi plantilla HTML.
<div class="content-container" *ngFor="let i of helperArray">
<general-information></general-information>
<textfields></textfields>
</div>
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>
Sé que pidió específicamente hacerlo usando * ngFor, pero quería compartir la forma en que resolví esto usando una directiva estructural:
import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
@Directive({ selector: '[appRepeat]' })
export class RepeatDirective {
constructor(private templateRef: TemplateRef<any>, private viewContainerRef: ViewContainerRef) {
}
@Input() set appRepeat(loops: number) {
for (let index = 0; index < loops; ++index) {
this.viewContainerRef.createEmbeddedView(this.templateRef);
}
}
}
Con eso puedes usarlo así:
<div *appRepeat="15">
Testing
</div>
Puedes usar esto simplemente:
HTML
<div *ngFor="let i of Count">
TS
export class Component implements OnInit {
Count = [];
constructor() {
this.Count.length = 10; //you can give any number
}
ngOnInit(): void {}
}