Reputation: 233
Using something like this: https://netbasal.com/dynamically-creating-components-with-angular-a7346f4a982d I'm adding multiple components, the question is how do I remove the components later on based on which was clicked? what I'm trying to do is create breadCrumbs, and when clicking on the crumb, remove it all all below it. to create them I use this code:
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;
}
all this works perfectly, but I add multiples of this. the question is how do I remove specific ones while leaving the rest?
Upvotes: 3
Views: 10152
Reputation: 105537
You can call destroy method on it:
createComponent(type) {
this.container.clear();
const factory: ComponentFactory = this.resolver.resolveComponentFactory(AlertComponent);
this.componentRef: ComponentRef = this.container.createComponent(factory);
setTimeout(()=>{
this.componentRef.destroy(); <--------------------
}, 2000);
}
I'm using a timeout here for demonstration purposes so that a component can be seen rendered on the screen.
Upvotes: 5
Reputation: 28909
You can now use subject
instead of interface
for components' communication
Removing child components from parent so communication between them must be started but how?
Using interface in this case
What's happening ?
Parent is creating the childs and when a child tries to remove itself, it tells its parent via interface to remove it so the parent does.
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);
}
If you want to test this just create a file like comp.ts and paste that code in this file and add references to the 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,
],
Upvotes: 1
Reputation: 41571
Alternatively if you are using ViewContainerRef to hold the injected component ,you can use the clear()
method .
this.container.clear();
Upvotes: 0