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