Comment utiliser *ngFor
pour répéter un élément HTML plusieurs fois?
Par exemple: si une variable membre est affectée à 20. Comment utiliser la directive * ngFor pour faire répéter un div 20 fois?
Comment utiliser *ngFor
pour répéter un élément HTML plusieurs fois?
Par exemple: si une variable membre est affectée à 20. Comment utiliser la directive * ngFor pour faire répéter un div 20 fois?
Réponses:
Vous pouvez utiliser les éléments suivants:
@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;
}
Ou implémentez un tube personnalisé:
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">
Remplacez 20
par votre variable
<ng-container *ngFor="let i of [].constructor(20)">🐱</ng-container>
génère 🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱
Il y a deux problèmes avec les solutions recommandées en utilisant Arrays
:
Il semble plus efficace de définir un Pipe
(une fois), en retournant 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;
}
}
Exemple d'utilisation (rendu d'une grille avec largeur / hauteur dynamique):
<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>
Vous pouvez simplement le faire dans votre HTML:
*ngFor="let number of [0,1,2,3,4,5...,18,19]"
Et utilisez la variable "nombre" pour indexer.
20
à une variable membre .. donc cela n'aidera pas beaucoup
*ngFor="let number of [0,1,2,3,4,5...,199,200]"
:-D
Une solution plus simple et réutilisable peut-être d'utiliser une directive structurelle personnalisée comme celle-ci.
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);
}
}
}
Et utilisez-le comme ceci:
<span *appTimes="3" class="fa fa-star"></span>
Le moyen le plus efficace et le plus concis d'y parvenir est d'ajouter un utilitaire d'itération. Ne vous embêtez pas à donner des valeurs. Ne vous embêtez pas à définir une variable dans la directive 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 vous utilisez Lodash , vous pouvez effectuer les opérations suivantes:
Importez Lodash dans votre composant.
import * as _ from "lodash";
Déclarez une variable membre dans le composant pour référencer Lodash.
lodash = _;
Ensuite, dans votre vue, vous pouvez utiliser la fonction de plage . 20 peut être remplacé par n'importe quelle variable de votre composant.
*ngFor="let number of lodash.range(20)"
Il faut dire que la liaison à des fonctions dans la vue peut être coûteuse, selon la complexité de la fonction que vous appelez, car la détection de changement appellera la fonction à plusieurs reprises.
Vous n'avez pas besoin de remplir le tableau comme suggéré dans la plupart des réponses. Si vous utilisez index dans votre ngFor
boucle, il vous suffit de créer un tableau vide avec la longueur correcte:
const elements = Array(n); // n = 20 in your case
et à votre avis:
<li *ngFor="let element in elements; let i = index">
<span>{{ i }}</span>
</li>
Approche plus simple:
Définissez un helperArray et instanciez-le dynamiquement (ou statique si vous le souhaitez) avec la longueur du nombre que vous souhaitez créer vos éléments HTML. Par exemple, je souhaite obtenir des données du serveur et créer des éléments avec la longueur du tableau renvoyé.
export class AppComponent {
helperArray: Array<any>;
constructor(private ss: StatusService) {
}
ngOnInit(): void {
this.ss.getStatusData().subscribe((status: Status[]) => {
this.helperArray = new Array(status.length);
});
}
}
Ensuite, utilisez le helperArray dans mon modèle HTML.
<div class="content-container" *ngFor="let i of helperArray">
<general-information></general-information>
<textfields></textfields>
</div>
Voici une version légèrement améliorée de la directive structurelle d'Ilyass Lamrani qui vous permet d'utiliser l'index dans votre modèle:
@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);
}
}
}
Usage:
<li *appRepeat="let i of myNumberProperty">
Index: {{i}}
</li>
Je sais que vous avez spécifiquement demandé de le faire en utilisant * ngFor, mais je voulais partager la façon dont j'ai résolu cela en utilisant une directive structurelle:
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);
}
}
}
Avec cela, vous pouvez l'utiliser comme ceci:
<div *appRepeat="15">
Testing
</div>
Vous pouvez utiliser ceci simplement:
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 {}
}