0%

angular-loop-specific-times-in-template

今天在HackerRank上做Angular题目,偶然遇到一个循环固定次数的问题,这里记录一下。

假设需要在template里面循环count次,每次生成一个div,而count是后台api返回的一个变量,该如何实现呢?

方法一,使用数组

我能想到的最简单的方法,就是定义一个含有count个元素的数组,然后使用ngFor遍历这个数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
export class AppComponent implements OnInit {
nums: number[] = [];

ngOnInit() {
this.fetchData().then(count => {
// 创建含有count个元素的数组,数组元素的值无所谓,我们只用到元素个数。
this.nums = Array(count).fill(0);
})
}

// 模拟后台api返回的count
fetchData() {
// Random int between 0 - 10
const randomInt = Math.floor((Math.random() * 10))
return Promise.resolve(randomInt);
}
}

然后使用ngFor遍历这个数组。这样会循环生成count个div元素。

1
2
3
<ng-container *ngFor="let n of nums; let i = index">
<div>{{i}}</div>
</ng-container>

方法二,在模板中构造数组

1
2
3
<div *ngFor="let i of [].constructor(count).keys()">
第 {{i + 1}} 次循环 <!-- 显示从1开始的序号 -->
</div>

注意:该方法会导致一个错误:需要研究一下,为什么?

1
core.mjs:6662 ERROR RuntimeError: NG0100: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: '[object Array Iterator]'. Current value: '[object Array Iterator]'. Expression location: _AppComponent component. Find more at

方法三,使用自定义指令

使用时,需要在模块或者独立组件的imports中引入RepeatDirective,否则会报错。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 自定义指令代码
import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';

@Directive({
standalone: true,
selector: '[appRepeat]',
})
export class RepeatDirective {
constructor(
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef,
) {}

@Input('appRepeat') set count(value: number) {
this.viewContainer.clear(); // 清空容器
for (let i = 0; i < value; i++) {
this.viewContainer.createEmbeddedView(this.templateRef, {
$implicit: i + 1, // 传递索引值
});
}
}
}

调用自定义指令

1
2
3
<div *appRepeat="count; let i">
这是第 {{ i }} 次循环
</div>

方法四:自定义管道

使用时,需要在模块或者独立组件的imports中引入RangePipe,否则会报错。

1
2
3
4
5
6
7
8
9
10
11
import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
standalone: true,
name: 'range'
})
export class RangePipe implements PipeTransform {
transform(value: number): number[] {
return Array.from({ length: value }, (_, i) => i);
}
}

使用自定义管道

1
2
3
<div *ngFor="let i of count | range">
第 {{i + 1}} 次循环 <!-- 显示从1开始的序号 -->
</div>