html – 动态添加和删除Angular中的组件

目前的官方文档仅显示如何动态更改< ng-template>中的组件.标签. https://angular.io/guide/dynamic-component-loader

我想要实现的是,假设我有3个组件:标题,节和页脚,带有以下选择器:

<app-header>
<app-section>
<app-footer>

然后有6个按钮可以添加删除每个组件:添加标题,添加节和添加页脚

当我点击添加标题时,该页面添加< app-header>到呈现它的页面,所以页面将包含:

<app-header>

然后如果我单击Add Section两次,该页面现在将包含:

<app-header>
<app-section>
<app-section>

如果单击“添加页脚”,页面将包含所有这些组件:

<app-header>
<app-section>
<app-section>
<app-footer>

是否有可能在Angular中实现这一目标?请注意,ngFor不是我正在寻找的解决方案,因为它只允许向页面添加相同的组件,而不是不同的组件.

编辑:ngIf和ngFor不是我正在寻找的解决方案,因为模板已经预先确定.我正在寻找的东西就像是一堆组件或一组组件,我们可以轻松地添加,删除和更改数组的任何索引.

编辑2:为了使它更清楚,让我们有另一个例子说明为什么ngFor不起作用.假设我们有以下组件:

<app-header>
<app-introduction>
<app-camera>
<app-editor>
<app-footer>

现在,这里有一个新组件< app-description>,用户希望在其中插入< app-editor>. ngFor只有在我想要循环遍历的同一个组件时才有效.但是对于不同的组件,ngFor在这里失败了.

解决方法

您可以通过使用ComponentFactoryResolver动态创建组件然后将它们注入ViewContainerRef来完成您要实现的目标.动态执行此操作的一种方法是将组件的类作为函数的参数传递,该函数将创建并注入组件.

见下面的例子:

import {
  Component,ComponentFactoryResolver,Type,ViewChild,ViewContainerRef
} from '@angular/core';

// Example component (can be any component e.g. app-header app-section)
import { DraggableComponent } from './components/draggable/draggable.component';

@Component({
  selector: 'app-root',template: `
    <!-- Pass the component class as an argument to add and remove based on the component class -->
    <button (click)="addComponent(draggableComponentClass)">Add</button>
    <button (click)="removeComponent(draggableComponentClass)">Remove</button>

    <div>
      <!-- Use ng-template to ensure that the generated components end up in the right place -->
      <ng-template #container>

      </ng-template>
    </div>

  `
})
export class AppComponent {
  @ViewChild('container',{read: ViewContainerRef}) container: ViewContainerRef;

  // Keep track of list of generated components for removal purposes
  components = [];

  // Expose class so that it can be used in the template
  draggableComponentClass = DraggableComponent;

  constructor(private componentFactoryResolver: ComponentFactoryResolver) {
  }

  addComponent(componentClass: Type<any>) {
    // Create component dynamically inside the ng-template
    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(componentClass);
    const component = this.container.createComponent(componentFactory);

    // Push the component so that we can keep track of which components are created
    this.components.push(component);
  }

  removeComponent(componentClass: Type<any>) {
    // Find the component
    const component = this.components.find((component) => component.instance instanceof componentClass);
    const componentIndex = this.components.indexOf(component);

    if (componentIndex !== -1) {
      // Remove component from both view and array
      this.container.remove(this.container.indexOf(component));
      this.components.splice(componentIndex,1);
    }
  }
}

笔记:

>如果您希望以后更容易删除组件,可以在局部变量中跟踪它们,请参阅this.components.或者,您可以遍历ViewContainerRef中的所有元素.
>您必须将组件注册为条目组件.在模块定义中,将组件注册为entryComponent(entryComponents:[DraggableComponent]).

运行示例:
https://plnkr.co/edit/mrXtE1ICw5yeIUke7wl5

了解更多信息:
https://angular.io/guide/dynamic-component-loader

相关文章

vue阻止冒泡事件 阻止点击事件的执行 &lt;div @click=&a...
尝试过使用网友说的API接口获取 找到的都是失效了 暂时就使用...
后台我拿的数据是这样的格式: [ {id:1 , parentId: 0, name:...
JAVA下载文件防重复点击,防止多次下载请求,Cookie方式快速简...
Mip是什么意思以及作用有哪些