Lặp lại phần tử HTML nhiều lần bằng cách sử dụng ngFor dựa trên một số


103

Làm cách nào để sử dụng *ngForđể lặp lại một phần tử HTML nhiều lần?

Ví dụ: Nếu tôi có một biến thành viên được gán cho 20. Làm cách nào để sử dụng chỉ thị * ngFor để tạo một div lặp lại 20 lần?



bốn cách để đạt được điều tương tự, hãy đọc ở đây. stackoverflow.com/a/36356629/5043867
Pardeep Jain

Câu trả lời:


90

Bạn có thể sử dụng như sau:

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

Hoặc triển khai một đường ống tùy chỉnh:

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
lớp FillPipe phải triển khai PipeTransform
toumir

1
Vâng bạn đã đúng! Nó tốt hơn ;-) Cảm ơn vì đã chỉ ra điều này. Tôi đã cập nhật câu trả lời của mình cho phù hợp ...
Thierry Templier

6
Trong cách tiếp cận đầu tiên, tôi nghĩ bạn muốn nói arr=Array;?
Abdulrahman alsoghayer

3
bạn có thể làm một codepen không? nó không hoạt động: self.parentView.context.arr không phải là một chức năng
Bộ công cụ

1
Cảm ơn vì cách tiếp cận đầu tiên! Tôi không sử dụng .fill (1) và đang làm việc;)
gtamborero

76
<div *ngFor="let dummy of ' '.repeat(20).split(''), let x = index">

Thay thế 20bằng biến của bạn


2
Đây chắc chắn là một câu trả lời tuyệt vời
xuất hiện

lặp lại nên là 19; chiều dài-1.
Mert Mertce

Giải pháp thanh lịch cho một vấn đề khá bất tiện. Nhưng tôi đoán nó có tác động đến hiệu suất đối với một số lượng lớn các yếu tố?
Martin Eckleben

76
<ng-container *ngFor="let i of [].constructor(20)">🐱</ng-container>

tạo ra 🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱


11
Đây phải là câu trả lời chính xác .. Cho đến nay nó là câu ngắn gọn nhất!
Mantisimo

LỖI Phạm vi Lỗi: Độ dài mảng không hợp lệ. Điều này sẽ sụp đổ khi số lượng mèo để vẽ bằng không.
Tom Bevelander

Thực sự thích cách tiếp cận đơn giản đó!
F. Geißler

51

Có hai vấn đề với các giải pháp được đề xuất sử dụng Arrays:

  1. Thật lãng phí. Đặc biệt đối với số lượng lớn.
  2. Bạn phải xác định chúng ở đâu đó dẫn đến rất nhiều lộn xộn cho một hoạt động đơn giản và phổ biến như vậy.

Có vẻ hiệu quả hơn khi xác định một Pipe(một lần), trả về 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;
  }
}

Ví dụ sử dụng (hiển thị lưới với chiều rộng / chiều cao động):

<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

Bạn có thể đơn giản làm điều này trong HTML của mình:

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

Và sử dụng biến "số" để lập chỉ mục.


1
OP cho biết ông được gán 20cho một biến thành viên .. vì vậy đây sẽ không giúp nhiều
phil294

Điều gì sẽ xảy ra nếu tôi muốn lặp lại 200 lần?
Chax

1
@Chax Bạn không thể. :(
Muhammad bin Yusrat 21/02/19

2
@Chax Có gì sai với 200? *ngFor="let number of [0,1,2,3,4,5...,199,200]":-D
Stack Underflow

1
@StackUnderflow Đáng tiếc là tôi không được trả tiền theo ký tự. Nếu là tôi, tôi sẽ rao giảng rằng đó là cách duy nhất để đạt được điều đó: P (nghiêm túc chỉ là đừng;))
Chax

10

Một giải pháp đơn giản hơn và có thể tái sử dụng có thể sử dụng chỉ thị cấu trúc tùy chỉnh như thế này.

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

}

Và sử dụng nó như thế này:

<span *appTimes="3" class="fa fa-star"></span>

để biết thêm thông tin: netbasal.com/…
Ilyass Lamrani

4

Cách ngắn gọn và hiệu quả nhất để đạt được điều này là thêm tiện ích trình vòng lặp. Đừng bận tâm đến giá trị. Đừng bận tâm đến việc thiết lập một biến trong chỉ thị 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;
}

1

Nếu bạn đang sử dụng Lodash , bạn có thể làm như sau:

Nhập Lodash vào thành phần của bạn.

import * as _ from "lodash";

Khai báo một biến thành viên trong thành phần để tham chiếu Lodash.

lodash = _;

Sau đó, theo quan điểm của bạn, bạn có thể sử dụng hàm phạm vi . 20 có thể được thay thế bằng bất kỳ biến nào trong thành phần của bạn.

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

Phải nói rằng việc ràng buộc với các hàm trong khung nhìn có thể tốn kém, tùy thuộc vào độ phức tạp của hàm mà bạn đang gọi vì Phát hiện thay đổi sẽ gọi hàm nhiều lần.


1

Bạn không cần phải điền vào mảng như được đề xuất trong hầu hết các câu trả lời. Nếu bạn sử dụng chỉ mục trong ngForvòng lặp của mình, tất cả những gì bạn cần tạo là một mảng trống với độ dài chính xác:

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

và theo quan điểm của bạn:

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

0

Cách tiếp cận đơn giản hơn:

Xác định helperArray và khởi tạo nó động (hoặc tĩnh nếu bạn muốn) với độ dài của số lượng mà bạn muốn tạo các phần tử HTML của mình. Ví dụ: tôi muốn lấy một số dữ liệu từ máy chủ và tạo các phần tử với độ dài của mảng được trả về.

export class AppComponent {
  helperArray: Array<any>;

  constructor(private ss: StatusService) {
  }

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

Sau đó, sử dụng helperArray trong mẫu HTML của tôi.

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

0

Đây là phiên bản cải tiến một chút của chỉ thị cấu trúc của Ilyass Lamrani cho phép bạn sử dụng chỉ mục trong mẫu của mình:

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

}

Sử dụng:

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

0

Tôi biết bạn đã yêu cầu cụ thể làm điều đó bằng cách sử dụng * ngFor, nhưng tôi muốn chia sẻ cách tôi giải quyết vấn đề này bằng cách sử dụng chỉ thị cấu trúc:

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

Với điều đó, bạn có thể sử dụng nó như sau:

<div *appRepeat="15">
  Testing
</div>

0

Bạn có thể sử dụng điều này một cách đơn giản:

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 {}
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.