使用Angular时动态添加组件

我将介绍如何在点击按钮时动态插入Angular组件。

我将以下内容分成两部分进行解释。

    1. 将Angular组件动态插入(→首先在不考虑位置的情况下插入)

 

    在特定位置动态插入Angular组件

步骤1:动态插入Angular组件

创建能够动态插入的组件

在这里,我们将创建以下非常简单的组件。

...
import { Component } from '@angular/core';

@Component({
  selector: 'app-dynamic',
  template: `<p>dynamic works!</p>`
})
export class DynamicComponent {

}

在HTML上放置按钮。

点击按钮后,将执行onButtonClick()方法,并能够生成Angular组件。

...
<div>
  <button (click)="onButtonClick()">click!</button>
</div>

以动态方式插入Angular组件

使用ComponentFactory和viewContainerRef,将Angular组件插入。

    • 初期処理 ngOnInit() で、動的に DynamicComponent をコンパイルできる状態にします。

 

    クリックされた時に、 viewContainerRef.createComponent を利用し、コンポーネント生成を実行します。
...
import { Component, ComponentFactory, ComponentFactoryResolver, OnInit, ViewContainerRef } from '@angular/core';
import { DynamicComponent } from './dynamic/dynamic.component';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  factory: ComponentFactory<DynamicComponent>;

  constructor(
    public viewContainerRef: ViewContainerRef,
    private resolver: ComponentFactoryResolver) { }

  ngOnInit() {
    this.factory = this.resolver.resolveComponentFactory(DynamicComponent);
  }

  onButtonClick() {
    this.viewContainerRef.createComponent(this.factory);
  }
}

在@NgModule.entryComponents中添加动态插入的组件。

(3) 实现到(3)阶段,当点击按钮时,将显示错误信息:“未找到DynamicComponent的组件工厂。您是否将其添加到@NgModule.entryComponents中?”

按照指示添加entryComponents后,当按下按钮时,将完成动态显示Angular组件的过程。

...
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { DynamicComponent } from './dynamic/dynamic.component';


@NgModule({
  declarations: [
    AppComponent,
    DynamicComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent],
  entryComponents: [DynamicComponent] // Add entryComponents here!
})
export class AppModule { }

请在此处查看整个源代码的确认。

第二步,動態地將Angular組件插入到特定位置。

在假设 Step1 已完成的前提下,使用 @ViewChild 可以指定组件的放置位置。需要分别编辑 component.ts 和 html 文件。

...
export class AppComponent implements OnInit {
  factory: ComponentFactory<DynamicComponent>;
  // @ViewChild を追加
  @ViewChild('dynamic', { read: ViewContainerRef }) viewContainerRef: ViewContainerRef;

  // 不要になった ViewContainerRef をコンストラクタから削除
  constructor(
    private resolver: ComponentFactoryResolver) { }

以下略

在HTML中,我们可以在希望插入组件的位置上添加上述的 @ViewChild 定义的 #dynamic 标签。以下示例将确保组件在按钮上方生成。

...
<div #dynamic></div>
<div>
  <button (click)="onButtonClick()">click!</button>
</div>

在完成上述操作后,点击按钮,可以确认在按钮上显示”dynamic works!”。

请点击这里查看整个源代码。

填補缺失的部分

    • 今回の実装ではDOM要素を追加しているだけなので、DomSanitizerを利用して実装することもできます。

 

    コンポーネントを生成するロジックをServiceクラスに置くことで、ほかのコンポーネントから呼び出すことができるようにできます。詳しくは「参考」に載せているページで確認できます。

请提供一份参考。

    • Dynamically add Component in angular 2/4 – Stack Overflow

 

    • Angularで中身を動的に変えられるModalを作る【基本編】 – Carpe Diem

 

    • Dynamically add components to the DOM with Angular – Frontend Weekly – Medium

 

    ionic framework – What is entryComponents in angular ngModule? – Stack Overflow