Ulangi elemen HTML beberapa kali menggunakan ngFor berdasarkan angka

103

Bagaimana cara saya *ngFormengulang elemen HTML beberapa kali?

Misalnya: Jika saya memiliki variabel anggota yang ditetapkan ke 20. Bagaimana cara menggunakan direktif * ngFor untuk membuat div berulang 20 kali?

takeradi
sumber
Ada empat cara untuk mencapai hal yang sama, baca di sini. stackoverflow.com/a/36356629/5043867
Pardeep Jain

Jawaban:

90

Anda bisa menggunakan yang berikut ini:

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

Atau terapkan pipa khusus:

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
sumber
1
kelas FillPipe harus mengimplementasikan PipeTransform
toumir
1
Ya kau benar! Lebih baik ;-) Terima kasih telah menunjukkan hal ini. Saya memperbarui jawaban saya sesuai ...
Thierry Templier
6
Dalam pendekatan pertama, saya pikir Anda bermaksud mengatakan arr=Array;?
Abdulrahman Alsoghayer
3
bisakah kamu membuat codepen? tidak berfungsi: self.parentView.context.arr bukan fungsi
Toolkit
1
Terima kasih untuk pendekatan pertama! Saya tidak menggunakan .fill (1) dan berfungsi;)
gtamborero
76
<div *ngFor="let dummy of ' '.repeat(20).split(''), let x = index">

Ganti 20dengan variabel Anda

Aximili
sumber
2
Ini jelas merupakan jawaban yang bagus
edkeveked
ulangi harus 19; panjang-1.
Mert Mertce
Solusi elegan untuk masalah yang sangat tidak nyaman. Tapi saya kira itu memiliki dampak kinerja untuk sejumlah besar elemen?
Martin Eckleben
76
<ng-container *ngFor="let i of [].constructor(20)">🐱</ng-container>

menghasilkan 🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱

ttulka
sumber
11
Ini harus menjadi jawaban yang benar .. Sejauh ini yang paling ringkas!
Mantisimo
ERROR RangeError: Panjang array tidak valid. Ini akan macet ketika jumlah kucing yang akan digambar adalah nol.
Tom Bevelander
Benar-benar menyukai pendekatan sederhana itu!
F. Geißler
51

Ada dua masalah dengan solusi yang disarankan menggunakan Arrays:

  1. Itu boros. Khususnya untuk jumlah yang besar.
  2. Anda harus mendefinisikannya di suatu tempat yang menghasilkan banyak kekacauan untuk operasi yang sederhana dan umum seperti itu.

Tampaknya lebih efisien untuk mendefinisikan Pipe(sekali), mengembalikan 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;
  }
}

Contoh penggunaan (menampilkan petak dengan lebar / tinggi dinamis):

<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
sumber
26

Anda dapat dengan mudah melakukan ini di HTML Anda:

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

Dan gunakan variabel "angka" untuk mengindeks.

Dekonunes
sumber
1
OP mengatakan dia ditugaskan 20ke variabel anggota .. jadi ini tidak akan banyak membantu
phil294
Bagaimana jika saya ingin mengulang 200 kali?
Chax
1
@Chax Anda tidak bisa. :(
Muhammad bin Yusrat
2
@Chax Apa yang salah dengan 200? *ngFor="let number of [0,1,2,3,4,5...,199,200]":-D
Stack Underflow
1
@StackUnderflow Sayangnya saya tidak dibayar oleh karakter. Jika ya, saya akan berkhotbah bahwa itu adalah satu-satunya cara untuk mencapai itu: P (serius saja jangan;))
Chax
10

Solusi yang lebih sederhana dan dapat digunakan kembali mungkin menggunakan arahan struktural kustom seperti ini.

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

}

Dan gunakan seperti ini:

<span *appTimes="3" class="fa fa-star"></span>
Ilyass Lamrani
sumber
untuk info lebih lanjut: netbasal.com/…
Ilyass Lamrani
4

Cara paling efisien dan ringkas untuk mencapai ini adalah dengan menambahkan utilitas iterator. Jangan repot-repot memberikan nilai. Jangan repot-repot menyetel variabel di direktif 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;
}
Amit Portnoy
sumber
1

Jika Anda menggunakan Lodash , Anda dapat melakukan hal berikut:

Impor Lodash ke dalam komponen Anda.

import * as _ from "lodash";

Deklarasikan variabel anggota dalam komponen untuk mereferensikan Lodash.

lodash = _;

Kemudian dalam pandangan Anda, Anda dapat menggunakan fungsi jangkauan . 20 dapat diganti dengan variabel apa pun di komponen Anda.

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

Harus dikatakan bahwa mengikat fungsi dalam tampilan mungkin mahal, tergantung pada kompleksitas fungsi yang Anda panggil karena Deteksi Perubahan akan memanggil fungsi tersebut berulang kali.

Davy
sumber
1

Anda tidak perlu mengisi larik seperti yang disarankan di sebagian besar jawaban. Jika Anda menggunakan index dalam ngForloop Anda, yang perlu Anda buat hanyalah array kosong dengan panjang yang benar:

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

dan menurut pandangan Anda:

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

Pendekatan yang lebih sederhana:

Definisikan helperArray dan buat instance secara dinamis (atau statis jika Anda mau) dengan panjang hitungan yang Anda inginkan untuk membuat elemen HTML. Misalnya, saya ingin mendapatkan beberapa data dari server dan membuat elemen dengan panjang array yang dikembalikan.

export class AppComponent {
  helperArray: Array<any>;

  constructor(private ss: StatusService) {
  }

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

Kemudian gunakan helperArray di template HTML saya.

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

Berikut adalah versi yang sedikit lebih baik dari petunjuk struktural Ilyass Lamrani yang memungkinkan Anda menggunakan indeks di templat Anda:

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

}

Pemakaian:

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

Saya tahu Anda secara khusus meminta untuk melakukannya menggunakan * ngFor, tetapi saya ingin berbagi cara saya menyelesaikan ini menggunakan arahan struktural:

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

Dengan itu Anda bisa menggunakannya seperti ini:

<div *appRepeat="15">
  Testing
</div>
Javier CampΓ³n
sumber
0

Anda dapat menggunakan ini dengan mudah:

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
sumber