🪐

Angular v18 で ng-content にフォールバックのコンテンツをサポートされます

2024/05/05に公開

Angular v18で入る予定の機能の紹介です。

概要

Angular では使いたいコンテンツを別のコンポーネント内に挿入または投影することができます。
具体的には ng-content ng-container ng-template などのタグを利用します。

https://angular.jp/guide/content-projection#条件付きのコンテンツ投影

Angular v18 では ng-content にデフォルトのコンテンツを指定できるようです。

https://github.com/angular/angular/pull/54854

別のコンポーネントからコンテンツが挿入されなかった場合は、デフォルトのコンテンツを表示する実装が簡単になります。

Angular v17 以前での書き方

現在の ng-content には、デフォルトのコンテンツをフォールバックできません。
そのため、デフォルトのコンテンツを表示したい場合は自前で実装する必要があります。

実装の一例として ng-content を含む子ノードをチェックし何もコンテンツが設定されてない(= DOMが描写されていない)場合に特定のコンテンツを表示するように記述していました。

@Component({
  ...
  template: `
    <h2>Child Component</h2>
    <div #ref>
      <ng-content></ng-content>
    </div>
    <div *ngIf="ref.childNodes.length == 0">
      Default Child Text
    </div>
  `
})
...

Angular v18 での書き方

Angular v18 ではよりシンプルになります。
ng-content の中にデフォルトのコンテンツを設定するだけです。

@Component({
  ...
  template: `
    <h2>Child Component</h2>
    <ng-content>Default Child Text</ng-content>
  `
})
...

Angular v17以前の書き方に比べると、余計な div タグを追加したり、DOM のチェックをする必要がなくなるので非常にわかりやすくなります。

注意点

Angularのコンテンツ投影はコンポーネントの作成時に行われます。
そのため、コンテンツの内容を動的に変更しても、デフォルトの内容は表示されません。

例えば、描写後のユーザーの行動(ボタンクリックなど)で、ifブロックがtrueからfalseになった場合はデフォルトが表示されないようです。

Note: Angular's content projection happens during creation time. This means that dynamically changing the contents of the slot will not cause the default content to show up, e.g. if a if block goes from true to false.
https://github.com/angular/angular/pull/54854

参考

ng-content の改善PR(関連 issue が立ったのは2016年なので、8年越しの嬉しい改善です)

https://github.com/angular/angular/pull/54854

今回紹介した内容を含むその他の Angular v18 でのリリース内容は ng-japan onair の公式動画がおすすめです

https://www.youtube.com/live/Pq8PebgdYLo?si=cIwPNpnZCAmXPsvP

Discussion