Angular TIPS

Angular TIPS

複数の要素を繰り返し出力するには?(ngFor)

2017年11月13日

配列の内容を順に出力できるngForディレクティブ(=ngForOfディレクティブ)と、ダミーのコンテナー要素(<ng-container>)を使うことで、複数の要素群をまとめて繰り返し出力する方法を説明する。

  • このエントリーをはてなブックマークに追加

【対応バージョン】 Angular 4以降。v4時点で執筆しました。

 ngForディレクティブ*1は、ディレクティブを指定した要素の開始タグから終了タグまでをひとまとまりとして、出力を繰り返します。その性質上、複数の要素をngForで出力することはできません。

 例えば以下は、<dt><dd>要素を繰り返し出力することを意図したコードですが、そうはなりません。<dt>要素だけを繰り返し出力します。

TypeScript
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
  <dl>
  <dt *ngFor="let article of articles">{{article.title}}</dt>
  <dd>{{article.url}} /( {{article.released | date: 'mediumDate'}}</dd>
  </dl>
  `,
})
export class AppComponent  { 
  articles = [
    {
      url: 'http://www.buildinsider.net/web/jqueryref',
      title: 'jQuery逆引きリファレンス',
      author: 'WINGSプロジェクト',
      released: new Date(2017, 10, 1)
    },
    ……中略……
  ]  
}
リスト1 複数の要素セットを繰り返し出力するためのコード(ダメな例。app.component.ts)
HTML
<dl>
  <!--bindings={
  "ng-reflect-ng-for-of": "[object Object],[object Object"
}-->
  <dt>jQuery逆引きリファレンス</dt>
  <dt>Angular TIPS</dt>
  <dt>jQuery Mobile逆引きリファレンス</dt>
  <dt>Web業界で働くためのPHP入門</dt>
  <dt>Tessel 2ではじめるセンサー電子工作入門</dt>
  <dd></dd>
</dl>
リスト2 <dt>要素だけが繰り返しの対象になっている(開発者ツールから確認)

 果たして、<dt>要素だけが繰り返しの対象になっていることが確認できます*2。この対策として、繰り返したい要素群をまとめて<div>要素などでくくるという方法が考えられます。しかし、Angular側の都合で余計な要素を増やすのは、あまり望ましい状態ではありません。

  • *2 開発者ツール上でも「Cannot read property 'url' of undefined」のようなエラーが表示されますが、<dd>要素がngForループの外になっているのが原因です。現時点では無視して構いません。

 このような場合には、ダミーのコンテナー要素として<ng-container>要素を利用してください。これによって、ngForディレクティブは<ng-container>要素配下の子要素群を繰り返し出力します(=<ng-container>要素そのものは出力しません)。

 以下は、その具体的なコードです。

TypeScript
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
  <dl>
  <ng-container *ngFor="let article of articles">
    <dt>{{article.title}}</dt>
    <dd>{{article.url}}{{article.released | date: 'mediumDate'}}</dd>
  </ng-container>
  </dl>
  `,
})
リスト3 複数の要素セットを繰り返し出力するためのコード(修正版。app.component.ts)
HTML
<dl>
  <!--bindings={
  "ng-reflect-ng-for-of": "[object Object],[object Object"
}-->
    <!---->
    <dt>jQuery逆引きリファレンス</dt>
    <dd>http://www.buildinsider.net/web/jqueryref(2017年11月1日)</dd>
  <!---->
    <dt>Angular TIPS</dt>
    <dd>http://www.buildinsider.net/web/angulartips(2017年10月10日)</dd>
  <!---->
    <dt>jQuery Mobile逆引きリファレンス</dt>
    <dd>http://www.buildinsider.net/web/jquerymobileref(2016年3月9日)</dd>
  <!---->
    <dt>Web業界で働くためのPHP入門</dt>
    <dd>http://www.atmarkit.co.jp/ait/series/1432/(2017年3月27日)</dd>
  <!---->
    <dt>Tessel 2ではじめるセンサー電子工作入門</dt>
    <dd>hhttps://codezine.jp/article/corner/693(2017年3月9日)</dd>
</dl>
リスト4 <dt>/<dd>要素が繰り返しの対象になっている(開発者ツールから確認)

 今度は、<dt><dd>要素の範囲で繰り返し処理が実行されていることが確認できます。

処理対象:構造ディレクティブ(Structural directives) カテゴリ:基本
処理対象:<ng-container>|マイクロシンタックス(Microsyntax) カテゴリ:構造ディレクティブ(Structural directives)
処理対象:テンプレート構文(Template Syntax) カテゴリ:基本
処理対象:NgFor カテゴリ:テンプレート構文(Template Syntax) > ビルトイン構造ディレクティブ(Built-in structural directives)
処理対象:*ngForマイクロシンタックス(*ngFor microsyntax) カテゴリ:テンプレート構文(Template Syntax) > ビルトイン構造ディレクティブ(Built-in structural directives) > NgFor
API:NgForOf(*ngFor) カテゴリ:@angular > common > DIRECTIVE(ディレクティブ)

※以下では、本稿の前後を合わせて5回分(第26回~第30回)のみ表示しています。
 連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。

26. インラインフレームに外部リソースをバインドするには?(Property Binding)

セキュリティの観点からデフォルトではiframeのsrc属性やobjectのdata属性にはプロパティバインディングできない。これを回避して信頼できる値としてバインディングする方法を説明する。

27. 要素に適用するスタイルクラスを操作するには?(Class Binding)

スタイルシートとして定義した対象クラスのスタイルを、任意の要素のclass属性に簡単に着脱できるClass Bindingの基本的な使い方を説明する。

28. 配列の内容を順に出力するには?(ngFor)

配列の内容を順に出力できるngForディレクティブ(=ngForOfディレクティブ)の基本的な使い方を説明。また、ngForディレクティブで利用できる特殊変数についてまとめる。

29. 【現在、表示中】≫ 複数の要素を繰り返し出力するには?(ngFor)

配列の内容を順に出力できるngForディレクティブ(=ngForOfディレクティブ)と、ダミーのコンテナー要素(<ng-container>)を使うことで、複数の要素群をまとめて繰り返し出力する方法を説明する。

30. 条件式に応じて要素を表示/非表示にするに?(ngIf)

与えられた条件式に基づき要素の表示/非表示を切り替えるngIfディレクティブの基本的な使い方を説明。また、ngIfディレクティブによる表示/非表示の挙動の特性と注意点も示す。

サイトからのお知らせ

Twitterでつぶやこう!