ディレクティブ合成API
Angularディレクティブは、再利用可能な動作をカプセル化する素晴らしい方法を提供します。 ディレクティブは、属性、CSSクラス、およびイベントリスナーを要素に適用できます。
ディレクティブ合成API を使用すると、 コンポーネントのTypeScriptクラスの内部からコンポーネントのホスト要素にディレクティブを適用できます。
コンポーネントにディレクティブを追加する
コンポーネントにディレクティブを適用するには、コンポーネントのデコレーターに hostDirectives プロパティを追加します。
このようなディレクティブをホストディレクティブと呼びます。
この例では、MenuBehavior ディレクティブを AdminMenu のホスト要素に適用します。
これは、テンプレートの <admin-menu> 要素に MenuBehavior を適用するのと同じように機能します。
@Component({ selector: 'admin-menu', template: 'admin-menu.html', hostDirectives: [MenuBehavior],})export class AdminMenu { }
フレームワークがコンポーネントをレンダリングすると、Angularは各ホストディレクティブのインスタンスも作成します。 ディレクティブのホストバインディングは、コンポーネントのホスト要素に適用されます。 デフォルトでは、ホストディレクティブの入力と出力は、コンポーネントの公開APIの一部として公開されません。 詳細については、以下の入力と出力を含めるを参照してください。
Angularはコンパイル時に静的にホストディレクティブを適用します。 ランタイム時には動的にディレクティブを追加できません。
hostDirectives で使用されるディレクティブは standalone: false を指定できません。
Angularは hostDirectives プロパティで適用されたディレクティブの selector を無視します。
入力と出力を含める
コンポーネントに hostDirectives を適用すると、
ホストディレクティブからの入力と出力は、デフォルトではコンポーネントのAPIには含まれません。
hostDirectives のエントリを拡張することで、コンポーネントのAPIに入力と出力を明示的に含めることができます。
@Component({ selector: 'admin-menu', template: 'admin-menu.html', hostDirectives: [{ directive: MenuBehavior, inputs: ['menuId'], outputs: ['menuClosed'], }],})export class AdminMenu { }
入力と出力を明示的に指定することで、hostDirective を持つコンポーネントのコンシューマーは
テンプレートでそれらにバインドできます。
<admin-menu menuId="top-menu" (menuClosed)="logMenuClosed()">
さらに、hostDirective から入力と出力をエイリアスして、
コンポーネントのAPIをカスタマイズできます。
@Component({ selector: 'admin-menu', template: 'admin-menu.html', hostDirectives: [{ directive: MenuBehavior, inputs: ['menuId: id'], outputs: ['menuClosed: closed'], }],})export class AdminMenu { }
<admin-menu id="top-menu" (closed)="logMenuClosed()">
別のディレクティブにディレクティブを追加する
コンポーネントに加えて、他のディレクティブにも hostDirectives を追加できます。
これにより、複数の動作を推移的に集約できます。
次の例では、Menu と Tooltip の2つのディレクティブを定義しています。
次に、MenuWithTooltip でこれらの2つのディレクティブの動作を構成します。
最後に、SpecializedMenuWithTooltip に MenuWithTooltip を適用します。
SpecializedMenuWithTooltip がテンプレートで使用されると、
Menu、Tooltip、MenuWithTooltip のすべてをインスタンス化します。
これらのディレクティブの各ホストバインディングは、SpecializedMenuWithTooltip のホスト要素に適用されます。
@Directive({...})export class Menu { }@Directive({...})export class Tooltip { }// MenuWithTooltip は、他の複数のディレクティブから動作を構成できます@Directive({ hostDirectives: [Tooltip, Menu],})export class MenuWithTooltip { }// CustomWidget は、すでに構成されている MenuWithTooltip からの動作を適用できます@Directive({ hostDirectives: [MenuWithTooltip],})export class SpecializedMenuWithTooltip { }
ホストディレクティブのセマンティクス
ディレクティブの実行順序
ホストディレクティブは、テンプレートで直接使用されるコンポーネントやディレクティブと同じライフサイクルを経ます。 ただし、ホストディレクティブは常に適用されているコンポーネントまたはディレクティブの前に、コンストラクターやライフサイクルフックおよびバインディングを実行します。
次の例は、ホストディレクティブの最小限の使用を示しています。
@Component({ selector: 'admin-menu', template: 'admin-menu.html', hostDirectives: [MenuBehavior],})export class AdminMenu { }
ここでの実行順序は次のとおりです。
MenuBehaviorがインスタンス化されるAdminMenuがインスタンス化されるMenuBehaviorが入力を受信する (ngOnInit)AdminMenuが入力を受信する (ngOnInit)MenuBehaviorがホストバインディングを適用するAdminMenuがホストバインディングを適用する
この動作順序により、hostDirectives を持つコンポーネントは、
ホストディレクティブで指定されたホストバインディングをオーバーライドできます。
この動作順序は次の例のように、 ホストディレクティブのネストされたチェーンにも適用されます。
@Directive({...})export class Tooltip { }@Directive({ hostDirectives: [Tooltip],})export class CustomTooltip { }@Directive({ hostDirectives: [CustomTooltip],})export class EvenMoreCustomTooltip { }
上記の例では、実行順序は次のとおりです。
Tooltipがインスタンス化されるCustomTooltipがインスタンス化されるEvenMoreCustomTooltipがインスタンス化されるTooltipが入力を受信する (ngOnInit)CustomTooltipが入力を受信する (ngOnInit)EvenMoreCustomTooltipが入力を受信する (ngOnInit)Tooltipがホストバインディングを適用するCustomTooltipがホストバインディングを適用するEvenMoreCustomTooltipがホストバインディングを適用する
依存性の注入
hostDirectives を指定するコンポーネントまたはディレクティブは、
それらのホストディレクティブのインスタンスを注入でき、その逆も可能です。
ホストディレクティブをコンポーネントに適用する場合、 コンポーネントとホストディレクティブの両方でプロバイダーを定義できます。
hostDirectives を持つコンポーネントと、それらのホストディレクティブの両方が同じ注入トークンを提供する場合、
hostDirectives を持つクラスで定義されたプロバイダーは
ホストディレクティブで定義されたプロバイダーよりも優先されます。