Angular v21 CDK Overlay でサポートされたネイティブ popover の紹介

に公開

11月20日に Angular v21 がリリースされた。

Vitest がテストランナーの標準になるなど多くの変更の中で、Angular CDK の Overlay において
Overlay Container を利用せずに ネイティブ popover を利用するオプションが追加された。ここでは Overlay Container を利用しないオプションと、この変更は我々開発者にとってどのようなメリットがあるのかを紹介したい。

https://github.com/angular/components/pull/32155

Overlay API とは何か

そもそも Overlay API とは何か、それは画面上でレイヤーが一段上のオーバーレイ表示を簡単に作成できるAngular CDK の API である。dialog や tooltip などを簡単に実現できる。

https://material.angular.dev/cdk/overlay/overview

このオーバーレイ表示は Overlay Container というものでハンドリングしている。Overlay Container の実態は、body に配置された単一の div 要素である。

以下のデモ動画を見てほしい。ダイアログを表示するボタンを押下すると<div class="cdk-overlay-container"></div>にダイアログが描画されていることがわかるだろう。これが Overlay Container である。

global dialog container

popoverのサポートにより脱 Overlay Container が可能に

Angular v21 から新たに ネイティブの popover の仕組みを利用することで、 Overlay Container を使わないオプションが新たに追加された。

まずは挙動を見てほしい。以下のデモ動画は Overlay Container を利用しない設定にした場合のものである。ダイアログボタンを押下しても <div class="cdk-overlay-container"></div>に描画されず、代わりに app-dialog-demo 内に popover="manual" の要素が追加されているのがわかるだろう。

inline dialog overlay

popover の設定方法

設定方法の1つ目は CdkConnectedOverlay ディレクティブの cdkConnectedOverlayUsePopover で設定する方法である。設定できるオプションは以下である。このオプションで inline を設定すれば良い。

  • global Overlay Container を利用する(デフォルト、今までの挙動)
  • inline トリガーの横に overlay を挿入する(脱 Overlay Container 化)
  • {type: 'parent', element: element} 指定した特定の子要素として挿入する(今回は紹介しない)

https://material.angular.dev/cdk/overlay/api#:~:text=cdkConnectedOverlayUsePopover

2つ目は CDK_CONNECTED_OVERLAY_DEFAULT_CONFIGトークンを使ってプロバイダーを登録する方法である。設定できる項目は cdkConnectedOverlayUsePopover と同じである。

export const appConfig: ApplicationConfig = {
  providers: [
    {
      provide: CDK_CONNECTED_OVERLAY_DEFAULT_CONFIG,
      useValue: {
        usePopover: 'inline',
      },
    },
  ],
};

脱 Overlay Container 化は何が嬉しいのか

脱 Overlay Container 化したところで、Angular SPA としてサービス開発をする分には体験は変わらない。しかし、Overlay を利用したコンポーネントを Angular Elements に変換して利用する際にメリットがある。

Angular Element とは、コンポーネントを Web Components (カスタム要素)として変換する機能である。これを利用することで特定のフレームワークに依存せず、Web標準のHTML要素と同じように利用できる。

https://angular.jp/guide/elements

Web Components のメリットとしてカプセル化がある。カスタム要素内にスコープを閉じることで外部に影響を与えずに利用できる。

しかし、Overlay Container を利用したコンポーネントをカスタム要素に変換すると、このメリットがなくなる。なぜかというと、Angular Elements(<my-element>)に変換しても、表示の実体はグローバルな Overlay Container に依存するためである。つまり、カスタム要素のスコープが完全に閉じられていない。

このカスタム要素の利用する場合、利用者の環境で Overlay Container が削除されると、<my-element> はポップアップなどを表示できない問題が発生する。つまり、利用者は自分が利用する <my-element> のほかに Overlay Container にも気を配る必要がある。

今回の popover のオプションにより、Overlay Container を利用しないということは、フローティングの実装がコンポーネント内に閉じられるということである。つまり、カスタム要素に変換した後も、カプセル化された要素として利用できる。

カスタム要素の利用者がカスタム要素の内部実装(Overlay Container)を意識しなくて済むのは、嬉しいメリットである。

Angular と Web 標準がどう親和していくのか

最近 Web の発展が目まぐるしく、Web 標準でできることが増えてきていると感じている。そのため今まであった Angular の仕組みが不要になったり、Angular と Web 標準の仕組みと組み合わて進化していくことが予想される。仕様が整理され、今までの課題が解決されることはいち開発者として非常に嬉しいことである。今後も Angular の進化を追っていきたい。

Angular Advent Calendar 2025、次回は KOHETs さんです。

Discussion