CodeZine(コードジン)

特集ページ一覧

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

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

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

自作ディレクティブをまとめるライブラリープロジェクトを作成

 Angularでは、ワークスペース内に複数のプロジェクトを定義できます(過去記事、次世代Webアプリケーションフレームワーク「Angular」の活用 第14回も参照)。本記事では、自作ディレクティブの再利用を想定して、Webページ本体のプロジェクトとは別のライブラリープロジェクトに自作ディレクティブを実装します。

 リスト2のコマンドで、ワークスペースとライブラリープロジェクトを作成できます。

[リスト2]ワークスペースとライブラリープロジェクトを作成するコマンド
ng new p002-attr #...(1)
cd p002-attr #...(2)
ng generate library my-libs --prefix=my #...(3)
ng generate directive marker1 --project my-libs #...(4)

 (1)でワークスペース(とWebページのプロジェクト)を作成後、(2)でそのフォルダーに移動して、(3)で「my-libs」という名前のライブラリープロジェクトを追加します。このとき、「--prefix」オプションで、ライブラリープロジェクトの接頭辞myを指定します。ディレクティブのスケルトンコードを作成するときは、(4)の通り「--project」オプションで生成先のプロジェクトを指定します。生成されたディレクティブには、ライブラリープロジェクトの接頭辞myがディレクティブ名に付与されます(詳細は後述)。

 実装したディレクティブを他のプロジェクトから利用できるように、ライブラリープロジェクトのモジュール定義ファイル(my-libs.module.ts)で、ディレクティブのクラスをエクスポートします。

[リスト3]ディレクティブをエクスポートする記述(p002-attr/projects/my-libs/src/lib/my-libs.module.ts)
@NgModule({
(略)
  exports: [
    Marker1Directive // ディレクティブをエクスポート
  ]
})
export class MyLibsModule { }

 ディレクティブを実装した後、リスト4のコマンドでライブラリープロジェクトをビルドします。ビルドされたライブラリープロジェクトが、dist/my-libsフォルダーに出力されます。

[リスト4]ライブラリープロジェクトをビルドするコマンド
ng build --project=my-libs

 Webページプロジェクトのモジュール定義ファイル(app.module.ts)では、リスト5の通りライブラリープロジェクトのモジュールをインポートして、ライブラリープロジェクトに含まれるディレクティブを利用できるようにします。

[リスト5]ライブラリープロジェクトをインポートする記述(p002-attr/src/app/app.module.ts)
@NgModule({
(略)
  imports: [
    BrowserModule,
    MyLibsModule // ライブラリープロジェクトのモジュールをインポート
  ],
(略)
})
export class AppModule { }

自作の属性ディレクティブを実装

 属性ディレクティブの実装方法を、マーカーペンのように要素を強調表示するディレクティブのサンプル(p002-attr)を用いて説明します。

属性ディレクティブの基本

 図1は、背景色とタイトル(マウスオーバー時に表示される文言)を設定する属性ディレクティブです。

図1:背景色とタイトルを設定するディレクティブ(p002-attr)
図1:背景色とタイトルを設定するディレクティブ(p002-attr)

 図1のディレクティブは、リスト6の通り実装します。

[リスト6]属性ディレクティブの実装(p002-attr/projects/my-libs/src/lib/marker1.directive.ts)
@Directive({ // ...(1)
  selector: '[myMarker1]' // ...(2)
})
export class Marker1Directive {
  // コンストラクター ...(3)
  constructor(private el: ElementRef) {
    this.el.nativeElement.style.backgroundColor = 'yellow'; // ...(4)
    this.el.nativeElement.title = 'ここは大事なのでマーク'; // ...(5)
  }
}

 ディレクティブのクラスには@Directiveデコレーター(1)を付与して、デコレーターのselector変数にディレクティブの名前(2)を指定します。リスト2(4)のコマンドでディレクティブのクラスを生成すると、リスト2(3)でライブラリープロジェクトに設定した接頭辞myがディレクティブ名に付与されて「myMarker1」となります。重複を防ぐため、ディレクティブ名には接頭辞を付与することが推奨されています。

 コンストラクター(3)で、要素に対応するElementRef型変数elを、依存性注入で受け取ります。受け取ったelのnativeElementプロパティでHTML要素を取得して、属性を指定します。ここでは(4)で背景色、(5)でタイトルを指定します。

 ディレクティブを利用する側は、リスト7の通り、HTMLタグの属性と似た記法でディレクティブ名「myMarker1」を記述します。ディレクティブを記述した<span>タグに囲まれた部分に、背景色とタイトルが設定されます。

[リスト7]リスト6のディレクティブを利用する記述(p002-attr/src/app/app.component.html)
<span myMarker1>鎌倉幕府</span>

属性ディレクティブを画面操作に反応させる

 属性ディレクティブには、ユーザーの画面操作に反応する処理を実装できます。マウスオーバー時に背景色を変える図2のサンプルで説明します。

図2:マウスオーバー時に背景色を変えるディレクティブ(p002-attr)
図2:マウスオーバー時に背景色を変えるディレクティブ(p002-attr)

 画面操作に反応する処理は、@HostListenerデコレーターの引数にイベントの種類を指定したメソッドで実装します。リスト8はmouseenter(マウスカーソルが当たったときのイベント)の処理で、背景色を変更しています。サンプルコードでは、mouseleave(マウスカーソルが離れたときのイベント)の処理も同様に実装しています。

[リスト8]マウスイベントに対応する属性ディレクティブの実装(p002-attr/projects/my-libs/src/lib/marker2.directive.ts)
@HostListener('mouseenter') onMouseEnter() {
  this.el.nativeElement.style.backgroundColor = 'pink';
}

属性ディレクティブにパラメーターを指定

 属性ディレクティブにパラメーターを指定する例を、図3のサンプルで説明します。このサンプルでは、背景色とタイトルをパラメーターとして指定できます。

図3:背景色とタイトルをパラメーターで指定するディレクティブ(p002-attr)
図3:背景色とタイトルをパラメーターで指定するディレクティブ(p002-attr)

 このサンプルでは、リスト9の通り、背景色をmyMarkerColor、タイトルをmyMarkerTitleで指定します。(1)のように値を直接指定するほか、(2)のようにコンポーネント変数の値をデータバインディングで指定することもできます。

[リスト9]ディレクティブにパラメーターを指定する記述(p002-attr/src/app/app.component.html)
<!-- 値を直接指定 ...(1) -->
<span myMarker3 myMarkerColor="#ffaa00" myMarkerTitle="絶対覚える!!">江戸幕府</span>
<!-- データバインディングでコンポーネント変数の値を指定 ...(2)-->
<span myMarker3 [myMarkerColor]="markerColor" [myMarkerTitle]="markerTitle">江戸幕府</span>

 リスト9で指定されたパラメーターを受け取るには、ディレクティブのクラスに、@Inputデコレーターを付与したプロパティを実装します。

[リスト10]パラメーターを受け取る属性ディレクティブの実装(p002-attr/projects/my-libs/src/lib/marker3.directive.ts)
@Input('myMarkerColor') set myMarkerColor(markerColor: string) {
  this.el.nativeElement.style.backgroundColor = markerColor;
}
@Input('myMarkerTitle') set myMarkerTitle(markerTitle: string) {
  this.el.nativeElement.title = markerTitle;
}

 値が変更されるたびに要素に反映させるため、setキーワードを利用して、設定値を引数で受け取るメソッド(いわゆるセッター)としてプロパティを実装します。ここでは、メソッドの引数で受け取った背景色やタイトルを、要素に反映するよう実装しています。

[補足]ディレクティブに直接パラメーターを指定できるようにする方法

 リスト11の[myMarker3a]のように、ディレクティブに直接パラメーターを指定させることもできます。

[リスト11]ディレクティブに直接パラメーターを指定する例(p002-attr/src/app/app.component.html)
<span [myMarker3a]="markerColor" [myMarkerTitle]="markerTitle">江戸幕府</span>

 ディレクティブに指定されたパラメーターを受け取るには、@Inputデコレーターの引数にディレクティブ名(ここではmyMarker3a)を設定します。

[リスト12]ディレクティブに指定されたパラメーターを受け取る実装(p002-attr/projects/my-libs/src/lib/marker3a.directive.ts)
@Input('myMarker3a') set myMarkerColor(markerColor: string) {

  • 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