【问题标题】:Angular 4 removing dynamically added componentsAngular 4 删除动态添加的组件
【发布时间】:2017-11-18 05:42:30
【问题描述】:

使用这样的东西: https://netbasal.com/dynamically-creating-components-with-angular-a7346f4a982d 我正在添加多个组件, 问题是我以后如何根据单击的内容删除组件? 我要做的是创建面包屑,然后单击面包屑时,将其全部删除。 要创建它们,我使用以下代码:

createCrumb(name, key, level){
  let data = {name:name, key:key, level,level, diagram: this.diagram};
  const factory = this.this.resolver.resolveComponentFactory(BreadCrumbsButton);
  let componentRef = this.container.createOmponent(factory);
  (<BreadCrumbsButton>componentRef.instance).data = data;
}

这一切都完美无缺,但我添加了这个的倍数。 问题是如何在保留其余部分的同时删除特定部分?

【问题讨论】:

  • 在这个问题中包含足够多的代码,使其具体且可回答,这将使其有可能获得更好的响应。
  • 嘿,my answer 有帮助吗?

标签: angular


【解决方案1】:

你可以在上面调用destroy方法:

  createComponent(type) {
    this.container.clear(); 
    const factory: ComponentFactory = this.resolver.resolveComponentFactory(AlertComponent);
    this.componentRef: ComponentRef = this.container.createComponent(factory);

    setTimeout(()=>{
       this.componentRef.destroy(); <--------------------
    }, 2000);
  }

我在这里使用超时来进行演示,以便可以看到在屏幕上呈现的组件。

【讨论】:

  • 为什么超时?不能同步销毁?
  • @Luckylooke,当然可以,只是为了演示。否则你不会在屏幕上看到任何东西,因为组件会在渲染后立即销毁。
  • @ Max Koretskyi aka Wizard,啊哈.. 好的.. 抱歉这个愚蠢的问题。快乐编码! :)
【解决方案2】:

也可以通过 Demo 检查这个答案

Dynamically ADDING and REMOVING Components in Angular


更新

您现在可以使用subject 代替interface 进行组件通信

Read about RxJS Subject


从父组件中移除子组件,因此必须启动它们之间的通信,但如何启动?

本例使用接口

发生了什么事?

父级正在创建子级,当子级尝试删除自己时,它会通过接口告诉其父级将其删除,因此父级会这样做。

import { ComponentRef, ComponentFactoryResolver, ViewContainerRef, ViewChild, Component } from "@angular/core";

// Parent Component
@Component({
    selector: 'parent',
    template: `
    <button type="button" (click)="createComponent()">
        Create Child
    </button>
    <div>
        <ng-template #viewContainerRef></ng-template>
    </div>
  `
})
export class ParentComponent implements myinterface {

    @ViewChild('viewContainerRef', { read: ViewContainerRef }) VCR: ViewContainerRef;

    //manually indexing the child components for better removal
    //although there is by-default indexing but it is being avoid for now
    //so index is a unique property here to identify each component individually.
    index: number = 0;

    // to store references of dynamically created components
    componentsReferences = [];

    constructor(private CFR: ComponentFactoryResolver) {
    }

    createComponent() {

        let componentFactory = this.CFR.resolveComponentFactory(ChildComponent);
        let componentRef: ComponentRef<ChildComponent> = this.VCR.createComponent(componentFactory);
        let currentComponent = componentRef.instance;

        currentComponent.selfRef = currentComponent;
        currentComponent.index = ++this.index;

        // prividing parent Component reference to get access to parent class methods
        currentComponent.compInteraction = this;

        // add reference for newly created component
        this.componentsReferences.push(componentRef);
    }

    remove(index: number) {

        if (this.VCR.length < 1)
            return;

        let componentRef = this.componentsReferences.filter(x => x.instance.index == index)[0];
        let component: ChildComponent = <ChildComponent>componentRef.instance;

        let vcrIndex: number = this.VCR.indexOf(componentRef)

        // removing component from container
        this.VCR.remove(vcrIndex);

        this.componentsReferences = this.componentsReferences.filter(x => x.instance.index !== index);
    }
}


// Child Component
@Component({
    selector: 'child',
    template: `
    <div>
    <h1 (click)="removeMe(index)">I am a Child, click to Remove</h1>
    </div>
    `
})
export class ChildComponent {

    public index: number;
    public selfRef: ChildComponent;

    //interface for Parent-Child interaction
    public compInteraction: myinterface;

    constructor() {
    }

    removeMe(index) {
        this.compInteraction.remove(index)
    }
}

// Interface
export interface myinterface {
    remove(index: number);
}

如果您想对此进行测试,只需创建一个类似 comp.ts 的文件并将该代码粘贴到该文件中,然后添加对 app.module.ts 的引用

@NgModule({
  declarations: [

    ParentComponent,
    ChildComponent

  ],
  imports: [

    //if using routing then add like so
    RouterModule.forRoot([
      { path: '', component: ParentComponent },
      { path: '**', component: NotFoundComponent }
    ]),

  ],
  entryComponents: [

    ChildComponent,  

  ],

【讨论】:

  • 我正在创建工具,您可以将 n 个拖放组件从侧边栏拖放到我们可以称为画布的主框架。我无法加载所有组件,因为它不可扩展。如果我将有 500 个组件,我不希望它们一次加载。所以我需要在第一次拖放 n 时延迟加载 ChildComponent 类。并且删除未使用的组件也会很好。但是我怎样才能懒惰地加载它们呢?也许我应该研究一下路由器插座代码它是如何工作的。
  • 你必须学习lazy-loading in Angular,那里还有很多文章。我会帮助你,但忙碌的日子
  • 谢谢,我找到了这个blog.angularindepth.com/…,这是迄今为止我找到的最有价值的。我现在正在玩它。
  • 希望,你正在朝着你的目标前进:)
【解决方案3】:

或者,如果您使用 ViewContainerRef 来保存注入的组件,您可以使用clear() 方法。

this.container.clear();

Github source

【讨论】:

  • clear 将删除所有项目,我需要根据被点击的项目删除特定项目
  • destroy 将如何工作。只是好奇。它不会完全摧毁吗?
  • @idekkers,比你可以使用remove 方法
猜你喜欢
  • 2017-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-15
  • 1970-01-01
  • 1970-01-01
  • 2020-09-09
  • 2018-08-11
相关资源
最近更新 更多