ディレクティブ
ディレクティブとは、HTML 要素に特別な振る舞いや制御を付与するための拡張機能のこと。
組み込み属性ディレクティブ
最も一般的な属性ディレクティブは以下の通り。
| 一般的なディレクティブ | 詳細 |
|---|---|
NgClass |
CSS クラスのセットを追加および削除する |
NgStyle |
HTML スタイルのセットを追加および削除する |
NgModel |
HTML フォーム要素に双方向データバインディングを追加する |
NgClass を使ってみる
ngClass を使用すると、複数の CSS クラスを同時に追加または削除できる。
<div [ngClass]="isSpecial ? 'special' : ''">This div is special</div>
クラスを追加したい要素に [ngClass] を追加する。isSpecial が true の場合、special クラスが適用される。
NgStyle を使ってみる
ngStyle を使用すると、複数のスタイルを同時に追加または削除できる。
currentStyles: Record<string, string> = {};
...
setCurrentStyles() {
this.currentStyles = {
'font-style': this.canSave ? 'italic' : 'normal',
'font-weight': !this.isUnchanged ? 'bold' : 'normal',
'font-size': this.isSpecial ? '24px' : '12px',
};
}
<div [ngStyle]="currentStyles">
This div is initially italic, normal weight, and extra large (24px).
</div>
スタイルを設定したい要素に [ngStyle] を追加する。setCurrentStyles メソッドが返すオブジェクトに応じたスタイルを当てることができる。
属性ディレクティブ
属性ディレクティブは要素の見た目や動作を変更するためのディレクティブの一種。
属性ディレクティブの作成
ここでは、要素の背景を黄色にするディレクティブを作成する。ディレクティブを作成するには Angular CLI の以下のコマンドを使用する。
ng generate directive highlight
src/app/highlight.directive.ts と、対応するテストファイル src/app/highlight.directive.spec.ts が作成される。
import {Directive} from '@angular/core';
@Directive({
selector: '[appHighlight]',
})
export class HighlightDirective {}
@Directive() デコレーターの構成プロパティは、ディレクティブの CSS 属性セレクター[appHighlight]を指定する。
背景を黄色にするロジックを追加する。
import {Directive, ElementRef, inject} from '@angular/core';
@Directive({
selector: '[appHighlight]',
})
export class HighlightDirective {
private el = inject(ElementRef);
constructor() {
this.el.nativeElement.style.backgroundColor = 'yellow';
}
}
属性ディレクティブの適用
適用方法はシンプルで、適用したい要素に対して appHighlight 属性をつけるだけ。
<p appHighlight>Highlight me!</p>
Angular は HighlightDirective クラスのインスタンスを作成し、
要素への参照をディレクティブのコンストラクターに注入する。これにより、
要素の背景スタイルが黄色に設定される。
ユーザーイベントの処理
ユーザーが要素内または要素外にマウスを移動したときに検出する方法と、ハイライトカラーを設定またはクリアして応答する方法について説明する。
@HostListener('mouseenter') onMouseEnter() {
this.highlight('yellow');
}
@HostListener('mouseleave') onMouseLeave() {
this.highlight('');
}
private highlight(color: string) {
this.el.nativeElement.style.backgroundColor = color;
}
@HostListener() デコレーターを使用し、イベントハンドラーを追加する。これだけ。
属性ディレクティブに値を渡す
HighlightDirective を適用するときのハイライトカラーを変更できることを例に、属性ディレクティブへの値の渡し方を説明する。
appHighlight = input('');
ディレクティブに input プロパティを追加する。これだけ。
使用するときに入力値をバインディングすればよい。
<p [appHighlight]="color">Highlight me!</p>
構造ディレクティブ
構造ディレクティブは HTML の構造(DOMの要素)を追加・削除する ディレクティブ。また構造ディレクティブは、<ng-template> 要素に適用され、その <ng-template> の内容を条件付きまたは繰り返しでレンダリングする。
構造ディレクティブは組込みの ngFor や ngIf を使う場面が多く、自作するケースはかなり限定的である。そのためこの記事でも説明を省いた部分は多い。自作したい場合はリファレンスを一読することをお勧めする。
構造ディレクティブの作成
ここでは、指定されたデータソースからデータを取得し、そのデータが利用可能になったときにテンプレートをレンダリングする構造ディレクティブを作成する。ディレクティブを作成するには Angular CLI の以下のコマンドを使用する。
ng generate directive select
src/app/select.directive.ts と、対応するテストファイル src/app/select.directive.spec.ts が作成される。
TemplateRef と ViewContainerRef をインポートし、ディレクティブ内で TemplateRef と ViewContainerRef をプライベートプロパティとしてインジェクトする。
import {Directive, TemplateRef, ViewContainerRef} from '@angular/core';
@Directive({
selector: '[select]',
})
export class SelectDirective {
private templateRef = inject(TemplateRef);
private viewContainerRef = inject(ViewContainerRef);
}
つづいて、入力プロパティを追加する。
export class SelectDirective {
// ...
selectFrom = input.required<DataSource>();
}
最後に、データを取得してテンプレートとそのデータをともにレンダリングするロジックを追加する。
export class SelectDirective {
// ...
async ngOnInit() {
const data = await this.selectFrom.load();
this.viewContainerRef.createEmbeddedView(this.templateRef, {
// テンプレートコンテキストに`$implicit`キーでデータを含むオブジェクトが含まれるように、
// 埋め込みビューを作成します。
$implicit: data,
});
}
}
使用例
<ng-template select let-data [selectFrom]="source">
<p>The data is: {{ data }}</p>
</ng-template>
構造ディレクティブの省略記法
構造ディレクティブは省略記法があり、<ng-template> を明示的に記述する必要がない。アスタリスク * をディレクティブ属性セレクターの前に付けることで、要素に直接適用できる。
<p *select="let data from source">The data is: {{data}}</p>
省略記法を使用する場合、要素ごとに適用できる構造ディレクティブは1つだけ。