数値に基づいてngForを使用してHTML要素を複数回繰り返す


103

*ngForHTML要素を複数回繰り返すにはどうすればよいですか?

例:メンバー変数が20に割り当てられている場合。* ngForディレクティブを使用してdivを20回繰り返すにはどうすればよいですか?



これを実現するには4つの方法があります。こちらをお読みください。stackoverflow.com/a/36356629/5043867
Pardeep Jain

回答:


90

以下を使用できます。

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

1
FillPipeクラスはPipeTransformを実装する必要があります
toumir

1
はい、あなたが正しい!それはより良いです;-)これを指摘してくれてありがとう 私はそれに応じて私の回答を更新しました...
Thierry Templier

6
最初のアプローチでは、あなたが言うつもりだったと思いますarr=Array;か?
Abdulrahman Alsoghayer 2016

3
コーデックペンを作れますか?機能しません:self.parentView.context.arrは関数ではありません
ツールキット

1
最初のアプローチをありがとう!私は.fill(1)を使用しておらず、動作しています;)
gtamborero 2017

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

20変数に置き換えます


2
これは間違いなく素晴らしい答えです。
edkeveked

repeatは19でなければなりません。長さ-1。
Mert Mertce、2018年

非常に不便な問題のためのエレガントなソリューション。しかし、それは多くの要素のパフォーマンスに影響を与えると思いますか?
Martin Eckleben

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

生成する


11
これが正解です。これは、最も簡潔です。
Mantisimo

エラーRangeError:配列の長さが無効です。これは、描く猫の数がゼロのときにクラッシュします。
Tom Bevelander

その単純なアプローチが本当に好きです!
F.ガイスラー

51

を使用した推奨ソリューションには2つの問題がありますArrays

  1. それは無駄です。特に多数の場合。
  2. それらをどこかで定義する必要があるため、そのような単純で一般的な操作では多くの混乱が生じます。

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>

26

HTMLでこれを簡単に行うことができます。

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

変数「number」を使用してインデックスを作成します。


1
OPは20、メンバー変数に割り当てたと述べた..これはあまり役に立たない
phil294

200回繰り返したい場合はどうなりますか?
Chax 2018年

1
@Chaxできません。:(
ムハンマドビンユスラット

2
@Chax 200の何が問題になっていますか?*ngFor="let number of [0,1,2,3,4,5...,199,200]":-D
スタックアンダーフロー

1
@StackUnderflow悲しいことに、私は文字で支払われていません。もしそうなら、それがそれを達成する唯一の方法であると私は説くでしょう:P(真剣にそうしないでください;))
Chax

10

より簡単で再利用可能なソリューションは、このようなカスタム構造ディレクティブを使用することです。

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>

詳細については、netbasal.com
Ilyass Lamrani、2017年

4

これを実現する最も効率的で簡潔な方法は、反復ユーティリティを追加することです。利回りの値を気にしないでください。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

Lodashを使用している場合は、次のことができます。

Lodashをコンポーネントにインポートします。

import * as _ from "lodash";

Lodashを参照するには、コンポーネント内でメンバー変数を宣言します。

lodash = _;

次に、ビューでrange関数を使用できます。20は、コンポーネント内の任意の変数で置き換えることができます。

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

変更検出は関数を繰り返し呼び出すため、呼び出す関数の複雑さによっては、ビュー内の関数へのバインドにコストがかかる可能性があることに注意してください。


1

ほとんどの回答で提案されているように配列を埋める必要はありません。ngForループでインデックスを使用する場合、作成する必要があるのは正しい長さの空の配列だけです。

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

そしてあなたの見解では:

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

0

よりシンプルなアプローチ:

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>

0

これは、テンプレートでインデックスを使用できるようにする、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>

0

* 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>

0

これは簡単に使用できます。

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 {}
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.