おさらい: ディレクティブとは
- ディレクティブとは、Angularのテンプレートの中で用いる特殊な指令である
- Componentと違い、HTMLの属性のように記述するという特徴がある
- 実は正確に言うとComponentはDirectiveの一種
- ディレクティブを用いることで、効率的なViewの制御を行うことができる
- ディレクティブには、属性ディレクティブと構造ディレクティブがある
構造ディレクティブの自作
今回作る構造ディレクティブ
- 設定されたCondtionがtrueなら表示し、falseなら消す
- つまり、
NgIf
の逆
構造ディレクティブの仕組み
- おさらい1: 属性ディレクティブの作成では、そのディレクティブが関連付けられた要素を参照することができた
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor(el: ElementRef) {
el.nativeElement.style.backgroundColor = 'yellow';
}
}
- おさらい2: 組み込みの構造ディレクティブでは、Angularが自動的に
ng-template
という要素を挿入し、そのテンプレートを操作することで、構造の変更を行っていた
*
は省略記法で、フルでは以下のような記載が必要になる。本来ngIfはng-templateが持つプロパティである。
<ng-template [ngIf]="show">
<p>test</p>
</ng-template>
構造ディレクティブの仕組み
- 構造ディレクティブでは、要素そのものではなく、その要素を含んで挿入されるテンプレートや、テンプレートが配置されるコンテナの参照を取得することができる
constructor(
private templateRef: TemplateRef<any>, // 挿入されるテンプレート
private viewContainer: ViewContainerRef // テンプレートが挿入されるコンテナ
) {}
- これらの参照を利用することで、構造そのものを組み替えるような操作が実現できる
構造ディレクティブを動作させる
Conditionを引数として取得するようにし、動作させるようにする
@Input() set appUnless(condition: boolean) {
// 表示が必要で、かつまだ要素が生成されていないときには、要素を生成して挿入する
if (!condition && !this.hasView) {
this.viewContainer.createEmbeddedView(this.templateRef);
this.hasView = true;
} else if (condition && this.hasView) {
this.viewContainer.clear();
this.hasView = false;
}
}