*ngForHTML要素を複数回繰り返すにはどうすればよいですか?
例:メンバー変数が20に割り当てられている場合。* ngForディレクティブを使用してdivを20回繰り返すにはどうすればよいですか?
*ngForHTML要素を複数回繰り返すにはどうすればよいですか?
例:メンバー変数が20に割り当てられている場合。* ngForディレクティブを使用してdivを20回繰り返すにはどうすればよいですか?
回答:
以下を使用できます。
@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変数に置き換えます
<ng-container *ngFor="let i of [].constructor(20)">🐱</ng-container>
生成する
を使用した推奨ソリューションには2つの問題がありますArrays。
Pipe(1回)を定義して、を返す方が効率的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]"
変数「number」を使用してインデックスを作成します。
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>
これを実現する最も効率的で簡潔な方法は、反復ユーティリティを追加することです。利回りの値を気にしないでください。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;
}
Lodashを使用している場合は、次のことができます。
Lodashをコンポーネントにインポートします。
import * as _ from "lodash";
Lodashを参照するには、コンポーネント内でメンバー変数を宣言します。
lodash = _;
次に、ビューでrange関数を使用できます。20は、コンポーネント内の任意の変数で置き換えることができます。
*ngFor="let number of lodash.range(20)"
変更検出は関数を繰り返し呼び出すため、呼び出す関数の複雑さによっては、ビュー内の関数へのバインドにコストがかかる可能性があることに注意してください。
よりシンプルなアプローチ:
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>
* 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>