CodeZine(コードジン)

特集ページ一覧

Webページ要素を操作できる「Angular」のディレクティブを自作してみよう

次世代Webアプリケーションフレームワーク「Angular」の活用 第20回

  • LINEで送る
  • このエントリーをはてなブックマークに追加
目次

自作の構造ディレクティブを実装

 次に、構造ディレクティブを自作する方法を説明します。

基本的な構造ディレクティブ

 まず、単純な例として、合言葉が一致したときにメッセージを表示する構造ディレクティブを、図4のサンプルで説明します。

図4:メッセージの表示を制御する構造ディレクティブ(p003-struct1)
図4:メッセージの表示を制御する構造ディレクティブ(p003-struct1)

 メッセージ表示部分の記述は、リスト13の通りです。myMatchKeywordディレクティブのパラメーターに、コンポーネント変数inputKeywordを設定しています。

[リスト13]構造ディレクティブを利用する記述(p003-struct1/src/app/app.component.html)
<div *myMatchKeyword="inputKeyword">
  <div>ディレクティブが指定された要素の内容です。</div>
  <div>合言葉に「Angular」と入力すると、この部分が表示されます。</div>
</div>

 ディレクティブの実装は、リスト14の通りです。

[リスト14]リスト13のディレクティブ実装(p003-struct1/projects/my-libs/src/lib/match-keyword.directive.ts)
// コンストラクター ...(1)
constructor(
  private templateRef: TemplateRef<any>,  // 表示内容のテンプレート
  private viewContainer: ViewContainerRef // 表示する場所
) { }
// プロパティ
@Input('myMatchKeyword') set myMatchKeyword(keyword: string) {
  // 現在の表示内容をクリア ...(2)
  this.viewContainer.clear();
  // 条件に合致したときに、テンプレートからビューを生成して追加 ...(3)
  if (keyword === 'Angular') {
    this.viewContainer.createEmbeddedView(this.templateRef);
  }
}

 コンストラクター(1)で、表示内容のテンプレートを表すtemplateRefと、表示する場所を表すviewContainerを、依存性注入で受け取ります。プロパティのセッターでは、(2)のviewContainer.clearメソッドで表示内容をクリア後、(3)のviewContainer.createEmbeddedViewメソッドで、テンプレートから実際の表示内容(ビュー)を生成して表示場所に追加します。

ngForのような繰り返し指定を受け付けるディレクティブ

 次に、ngForのように繰り返しの指定を受け付ける、図5のサンプルを説明します。OS(os)とスマートフォン名(name)を含むJavaScriptオブジェクトの配列から、OSが「iOS」のものを抽出して、スマートフォン名をリスト表示します。

図5:iOSのスマートフォンのみをリストする構造ディレクティブ(p004-struct2)
図5:iOSのスマートフォンのみをリストする構造ディレクティブ(p004-struct2)

 リスト表示部分の記述はリスト15の通りです。ngForディレクティブと同様に、表示する配列を「let <配列の要素> of <配列>」形式で指定します。

[リスト15]リスト表示ディレクティブの記述(p004-struct2/src/app/app.component.html)
<li *myPhoneFilter="let phone of phoneList">{{phone.name}}</li>

 ディレクティブの実装は、リスト16の通りです。

[リスト16]リスト15のディレクティブ実装(p004-struct2/project/my-libs/src/lib/phone-filter.directive.ts)
// 「let phone of phoneList」のphoneListを引数に受け取るセッター ...(1)
@Input('myPhoneFilterOf') set myPhoneFilterOf(inputValues: any[]) {
  this.viewContainer.clear(); // 現在の表示内容をクリア
  inputValues.forEach((value, input, array) => {
    if (value.os === 'iOS') {
      // テンプレートからビューを生成して追加 ...(2)
      this.viewContainer.createEmbeddedView(this.templateRef, {
        $implicit: value // $implicitは「phone」に対応 ...(3)
      });
    }
  });
}

 (1)のプロパティで、「let phone of phoneList」の「phoneList」配列を、セッターの引数inputValuesとして受け取ります。ここでポイントになるのはプロパティ名で、「let phone of phoneList」の「of」をディレクティブ名の後ろに付加した「myPhoneFilterOf」がプロパティ名になります。

 受け取った配列要素の「os」が「iOS」の場合のみ、(2)でテンプレートからビューを生成して追加します。このとき、createEmbeddedViewメソッドの第2引数に、テンプレートに適用する変数をJavaScriptオブジェクトで指定します。(3)の$implicitは、「let A of B」のAに対応する変数で、ここでは配列の要素を代入します。その結果、リスト15では「{{phone.name}}」という記述で、スマートフォン名を表示できます。

まとめ

 本記事では、要素の属性や構造を操作するAngularのディレクティブを取り上げて、自作ディレクティブの実装方法を説明しました。ディレクティブは、さまざまなHTML要素に適用できる共通の属性や処理を実装したい場合に便利です。また、これに関連して、ディレクティブを他のプロジェクトで再利用するときに便利なライブラリープロジェクトについて説明しました。

 次回は、Googleが推進するデザインガイドライン「Material Design」をAngularで利用できる「Angular Material」について解説します。

参考資料



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

バックナンバー

連載:次世代Webアプリケーションフレームワーク「Angular」の活用

もっと読む

著者プロフィール

  • WINGSプロジェクト  吉川 英一(ヨシカワ エイイチ)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂...

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XM...

あなたにオススメ

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5