Wiederholen Sie das HTML-Element mehrmals mit ngFor basierend auf einer Zahl

103

Wie kann ich *ngForein HTML-Element mehrmals wiederholen?

Zum Beispiel: Wenn ich eine Mitgliedsvariable 20 zugewiesen habe. Wie verwende ich die Direktive * ngFor, um ein Div 20 Mal wiederholen zu lassen?

takeradi
quelle
Es gibt vier Möglichkeiten , dasselbe zu erreichen. Lesen Sie hier. stackoverflow.com/a/36356629/5043867
Pardeep Jain

Antworten:

90

Sie könnten Folgendes verwenden:

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

Oder implementieren Sie eine benutzerdefinierte Pipe:

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;
}
Thierry Templier
quelle
1
Die FillPipe-Klasse muss PipeTransform
toumir
1
Ja, du hast Recht! Es ist besser ;-) Danke, dass du darauf hingewiesen hast. Ich habe meine Antwort entsprechend aktualisiert ...
Thierry Templier
6
Ich denke, Sie wollten im ersten Ansatz sagen arr=Array;?
Abdulrahman Alsoghayer
3
Kannst du einen Codepen machen? es funktioniert nicht: self.parentView.context.arr ist keine Funktion
Toolkit
1
Danke für den ersten Ansatz! Ich benutze die .fill (1) nicht und arbeite;)
gtamborero
76
<div *ngFor="let dummy of ' '.repeat(20).split(''), let x = index">

Ersetzen Sie 20durch Ihre Variable

Aximili
quelle
2
Dies ist definitiv eine großartige Antwort
edkeveked
Wiederholung sollte 19 sein; Länge-1.
Mert Mertce
Elegante Lösung für ein recht unbequemes Problem. Aber ich denke, es hat einen Leistungseffekt für eine große Anzahl von Elementen?
Martin Eckleben
76
<ng-container *ngFor="let i of [].constructor(20)">🐱</ng-container>

erzeugt 🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱

ttulka
quelle
11
Dies sollte die richtige Antwort sein. Es ist bei weitem die prägnanteste!
Mantisimo
ERROR RangeError: Ungültige Array-Länge. Dies stürzt ab, wenn die Anzahl der zu ziehenden Katzen Null ist.
Tom Brinkkemper
Mag diesen einfachen Ansatz wirklich!
F. Geißler
51

Es gibt zwei Probleme mit den empfohlenen Lösungen Arrays:

  1. Es ist verschwenderisch. Insbesondere für große Stückzahlen.
  2. Sie müssen sie irgendwo definieren, was für eine so einfache und übliche Operation zu viel Unordnung führt.

Es scheint effizienter zu sein, ein Pipe(einmaliges) zu definieren und ein 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;
  }
}

Anwendungsbeispiel (Rendern eines Rasters mit dynamischer Breite / Höhe):

<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>
Andreas Baumgart
quelle
26

Sie können dies einfach in Ihrem HTML tun:

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

Und verwenden Sie die Variable "Nummer" zum Indizieren.

Dekonunes
quelle
1
OP sagte, er 20habe einer Mitgliedsvariablen zugewiesen . Das wird also nicht viel helfen
phil294
Was ist, wenn ich 200 Mal iterieren möchte?
Chax
1
@Chax Sie können nicht. :(
Muhammad bin Yusrat
2
@Chax Was ist los mit 200? *ngFor="let number of [0,1,2,3,4,5...,199,200]":-D
Stack
1
@StackUnderflow Leider werde ich nicht von Charakteren bezahlt. Wenn ich es wäre, würde ich predigen, dass dies der einzige Weg ist, um Folgendes zu erreichen: P (ernsthaft einfach nicht;))
Chax
10

Eine einfachere und wiederverwendbare Lösung ist möglicherweise die Verwendung einer solchen benutzerdefinierten Strukturanweisung.

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

}

Und benutze es so:

<span *appTimes="3" class="fa fa-star"></span>
Ilyass Lamrani
quelle
Für weitere Informationen: netbasal.com/…
Ilyass Lamrani
4

Der effizienteste und präziseste Weg, dies zu erreichen, ist das Hinzufügen eines Iterator-Dienstprogramms. Machen Sie sich nicht die Mühe, Werte zu liefern. Machen Sie sich nicht die Mühe, eine Variable in der ngFor-Direktive festzulegen:

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;
}
Amit Portnoy
quelle
1

Wenn Sie Lodash verwenden , können Sie Folgendes tun:

Importieren Sie Lodash in Ihre Komponente.

import * as _ from "lodash";

Deklarieren Sie eine Mitgliedsvariable innerhalb der Komponente, um auf Lodash zu verweisen.

lodash = _;

In Ihrer Ansicht können Sie dann die Bereichsfunktion verwenden . 20 kann durch eine beliebige Variable in Ihrer Komponente ersetzt werden.

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

Es muss gesagt werden, dass das Binden an Funktionen in der Ansicht abhängig von der Komplexität der Funktion, die Sie aufrufen, kostspielig sein kann, da die Änderungserkennung die Funktion wiederholt aufruft.

Davy
quelle
1

Sie müssen das Array nicht wie in den meisten Antworten vorgeschlagen füllen. Wenn Sie in Ihrer ngForSchleife einen Index verwenden , müssen Sie lediglich ein leeres Array mit der richtigen Länge erstellen:

const elements = Array(n); // n = 20 in your case

und aus Ihrer Sicht:

<li *ngFor="let element in elements; let i = index">
  <span>{{ i }}</span>
</li>
Verwelken
quelle
0

Einfacherer Ansatz:

Definieren Sie ein helperArray und instanziieren Sie es dynamisch (oder statisch, wenn Sie möchten) mit der Länge der Anzahl, mit der Sie Ihre HTML-Elemente erstellen möchten. Zum Beispiel möchte ich einige Daten vom Server abrufen und Elemente mit der Länge des zurückgegebenen Arrays erstellen.

export class AppComponent {
  helperArray: Array<any>;

  constructor(private ss: StatusService) {
  }

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

Verwenden Sie dann das helperArray in meiner HTML-Vorlage.

<div class="content-container" *ngFor="let i of helperArray">
  <general-information></general-information>
  <textfields></textfields>
</div>
Florian Leitgeb
quelle
0

Hier ist eine leicht verbesserte Version der Strukturanweisung von Ilyass Lamrani, mit der Sie den Index in Ihrer Vorlage verwenden können:

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

}

Verwendung:

<li *appRepeat="let i of myNumberProperty">
    Index: {{i}}
</li>
MK10
quelle
0

Ich weiß, dass Sie ausdrücklich darum gebeten haben, dies mit * ngFor zu tun, aber ich wollte mitteilen, wie ich dies mithilfe einer strukturellen Richtlinie gelöst habe:

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

Damit können Sie es einfach so verwenden:

<div *appRepeat="15">
  Testing
</div>
Javier Campón
quelle
0

Sie können dies einfach verwenden:

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 {}
}
Janitha Rasanga
quelle