【发布时间】:2016-07-31 20:15:16
【问题描述】:
如何使用*ngFor 多次重复一个 HTML 元素?
例如: 如果我有一个分配给 20 的成员变量。如何使用 *ngFor 指令使 div 重复 20 次?
【问题讨论】:
-
有四种方法可以达到相同的效果,请在此处阅读。 stackoverflow.com/a/36356629/5043867
标签: angular
如何使用*ngFor 多次重复一个 HTML 元素?
例如: 如果我有一个分配给 20 的成员变量。如何使用 *ngFor 指令使 div 重复 20 次?
【问题讨论】:
标签: angular
<ng-container *ngFor="let i of [].constructor(20)">?</ng-container>
生成????????????????????
【讨论】:
_ 作为变量名,因为i 以undefined 结尾(因为数组为空)。如果您确实需要索引,您可以使用*ngFor="let _ of [].constructor(20); let catNumber=index",然后Cat number {{ catNumber + 1 }} ? 将向您显示猫号。如果你有嵌套循环,你可以为每个循环使用_,它们不会冲突。
您可以使用以下内容:
@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;
}
或者实现一个自定义管道:
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">
用你的变量替换20
【讨论】:
使用Arrays的推荐解决方案有两个问题:
定义一个Pipe(一次)似乎更有效,返回一个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;
}
}
使用示例(渲染具有动态宽度/高度的网格):
<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>
【讨论】:
您可以在 HTML 中简单地执行此操作:
*ngFor="let number of [0,1,2,3,4,5...,18,19]"
并使用变量“数字”进行索引。
【讨论】:
20 分配给一个成员变量.. 所以这不会有太大帮助
*ngFor="let number of [0,1,2,3,4,5...,199,200]" :-D
一个更简单且可重用的解决方案可能是使用这样的自定义结构指令。
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);
}
}
}
并像这样使用它:
<span *appTimes="3" class="fa fa-star"></span>
【讨论】:
this.viewContainer.clear();。
实现这一点的最有效和最简洁的方法是添加一个迭代器实用程序。不要费心产生价值。不要费心在 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;
}
【讨论】:
我知道你特别要求使用 *ngFor 来做这件事,但我想分享一下我使用结构指令解决这个问题的方法:
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);
}
}
}
你可以像这样使用它:
<div *appRepeat="15">
Testing
</div>
【讨论】:
@Input() set smpClone(loops: number) { while (--loops > 0) { this._viewContainerRef.createEmbeddedView(this._templateRef); } }
您不需要像大多数答案中建议的那样填充数组。如果您在ngFor 循环中使用索引,您只需创建一个长度正确的空数组:
const elements = Array(n); // n = 20 in your case
在你看来:
<li *ngFor="let element in elements; let i = index">
<span>{{ i }}</span>
</li>
【讨论】:
您可以简单地使用它:
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 {}
}
【讨论】:
如果您使用Lodash,您可以执行以下操作:
将Lodash 导入到您的组件中。
import * as _ from "lodash";
在组件中声明一个成员变量来引用 Lodash。
lodash = _;
那么在您看来,您可以使用range function。 20 可以替换为组件中的任何变量。
*ngFor="let number of lodash.range(20)"
必须说,绑定到视图中的函数可能代价高昂,具体取决于您调用的函数的复杂性,因为更改检测会重复调用该函数。
【讨论】:
进行第 n 次重复的最佳且简单的方法是 [].constructor(nth)
5次循环示例
<ng-container *ngFor="let _ of [].constructor(5); let i = index">
<b>{{ i }}</b>
</ng-container>
【讨论】:
更简单的方法:
定义一个 helperArray 并使用您想要创建 HTML 元素的计数长度动态(或静态,如果需要)实例化它。例如,我想从服务器获取一些数据并创建具有返回数组长度的元素。
export class AppComponent {
helperArray: Array<any>;
constructor(private ss: StatusService) {
}
ngOnInit(): void {
this.ss.getStatusData().subscribe((status: Status[]) => {
this.helperArray = new Array(status.length);
});
}
}
然后在我的 HTML 模板中使用 helperArray。
<div class="content-container" *ngFor="let i of helperArray">
<general-information></general-information>
<textfields></textfields>
</div>
【讨论】:
这是 Ilyass Lamrani 的结构指令的略微改进版本,它允许您在模板中使用索引:
@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);
}
}
}
用法:
<li *appRepeat="let i of myNumberProperty">
Index: {{i}}
</li>
【讨论】:
你可以这样做:
Ts:
CreateTempArray(number){
var arr=[];
for(let i=0;i<number;i++){
arr[i]="";
}
return arr;
}
HTML:
<div *ngFor="let i of CreateTempArray(20);">
cycle 20 times
</div>
【讨论】: