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?
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?
Câu trả lời:
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;
}
arr=Array;
?
<div *ngFor="let dummy of ' '.repeat(20).split(''), let x = index">
Thay thế 20
bằng biến của bạn
<ng-container *ngFor="let i of [].constructor(20)">🐱</ng-container>
tạo ra 🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱
Có hai vấn đề với các giải pháp được đề xuất sử dụng Arrays
:
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>
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.
20
cho một biến thành viên .. vì vậy đây sẽ không giúp nhiều
*ngFor="let number of [0,1,2,3,4,5...,199,200]"
:-D
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>
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;
}
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.
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 ngFor
vò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>
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>
Đâ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>
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>
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 {}
}