noxi雑記

.NET、Angularまわりの小ネタブログ

Angular9では動的に生成するComponentをentryComponentsに追加しなくて良い

Angular9 の変更点の1つとして entryComponentsの非推奨 があります。
詳しい理由は以下の記事に記述されていますが、 Ivy を有効にしていると entryComponents に追加した Component で無くても CompnentFactorey を利用できるようになったからです。

dev.to

では本当に不要になったのか、 Angular Material の Dialog で試してみます。

環境

Angular CLI: 9.0.2
Node: 12.16.0
OS: win32 x64

Angular: 9.0.1
... animations, common, compiler, compiler-cli, core, forms     
... language-service, platform-browser, platform-browser-dynamic
... router
Ivy Workspace: Yes

Package                           Version
-----------------------------------------------------------     
@angular-devkit/architect         0.900.2
@angular-devkit/build-angular     0.900.2
@angular-devkit/build-optimizer   0.900.2
@angular-devkit/build-webpack     0.900.2
@angular-devkit/core              9.0.2
@angular-devkit/schematics        9.0.2
@angular/cdk                      9.0.0
@angular/cli                      9.0.2
@angular/material                 9.0.0
@ngtools/webpack                  9.0.2
@schematics/angular               9.0.2
@schematics/update                0.900.2
rxjs                              6.5.4
typescript                        3.7.5
webpack                           4.41.2

ダイアログの表示

適当なコンポーネントを作成し、ダイアログを表示させます。

// src/app/app.component.ts

import { Component } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { SampleComponent } from './sample/sample.component';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {

  constructor(private readonly _dialog: MatDialog) {
  }

  showDialog() {
    this._dialog.open(SampleComponent);
  }

}
// src/app/app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { MatDialogModule } from '@angular/material/dialog';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { SampleComponent } from './sample/sample.component';

@NgModule({
  declarations: [
    AppComponent,
    SampleComponent
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    MatDialogModule,
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

entryComponents に表示対象のコンポーネントを追加していませんが、無事表示されました。

f:id:noxi515:20200216175908p:plain

終わりに

Angular8 まではダイアログみたいな動的に生成されるコンポーネントを使用する場合 entryComponents に追加する必要がありましたが、 Angular9 の Ivy 環境では不要になりました。
今までは LazyModule で使用されるサービスが LazyModule に所属するコンポーネントをダイアログとして表示する場合に、サービスの所属を provideIn: 'root' から特定のモジュールに変更する必要がありました。これはとてもとても面倒で、循環参照の発生や LazyModule 間で依存があった場合の更なるモジュール分割など、手元のプロジェクトでは色々な問題が生まれていました。
Angular9 に更新することで LazyModule の EntryComponents 問題に悩まなくても良くなるのはとても嬉しいです。