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


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

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


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 🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱


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>

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.


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>

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

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.


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>

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>

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>

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>

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 {}
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.