31

I have a parent component which opens a new component on click of a link, this new component is supposed to have a close button which on close sends a closing message to parent and destroy itself.

We can send the closing message using ngOnDestroy method, but how do I invoke the destroying of the child component.

<parent>
    <child></child> //child to be opened on click but close 
                    //event should be inside the child componenet
</parent>

Do correct me if i am having some conceptual mistake here. Thanks

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
Sumit Agarwal
  • 4,091
  • 8
  • 33
  • 49

3 Answers3

38

If you add a component using ViewContainerRef.createComponent() like shown in Angular 2 dynamic tabs with user-click chosen components, then the component can destroy itself when you pass cmpRef to the created component.

Otherwise I don't think there is a way. You can pass a value to the parent so that an *ngIf removes the component.

<child *ngIf="showChild" (close)="showChild = false"></child>
class ParentComponent {
  showChild:boolean = true;
}
class ChildComponent {
  @Output() close = new EventEmitter();

  onClose() {
    this.close.emit(null);
  }
}
Community
  • 1
  • 1
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • 2
    That's a neat solution, I also needed something like this few days ago and I did it exactly the same. Don't think there's a better way to achieve this at the moment. – Stefan Svrkota Sep 29 '16 at 08:05
  • @Günter Zöchbauer can you show how to use "close" in the child component's typescript please? How will we trigger the close event? – Bünyamin Sarıgül Oct 03 '16 at 08:44
  • anyway to do it for angular 1? – codenamezero Oct 02 '18 at 17:02
  • 6
    This is not the answer to this question. This is a component letting know the parent when to remove it. It's in the parent scope when the removal takes place... this is not self-destruction which is what the user was asking (what I came here for). – Jandro Rojas Jun 01 '19 at 20:20
  • Also, it's misleading. It says the component is passing a component reference to the parent which is not true. It's just emitting an event that the parent has to subscribe to. – Jandro Rojas Jun 01 '19 at 20:22
  • @JandroRojas sorry, don't understand what you are referring to. – Günter Zöchbauer Jun 01 '19 at 20:35
  • @GünterZöchbauer he is referring to the fact that the proposed mechanism is not entirely self-containted/encapsulated in a single component that destroys itself (based on some condition presummably). – Youp Bernoulli Oct 09 '20 at 14:40
20

Here is another way to do it. This works from within the component itself; no need to communicate with external components.

// imports
export class SelfDestroyableComponent implements OnInit {
    // other code

    constructor(private host: ElementRef<HTMLElement>) {}

    // whatEver function name you want to give 
    onCloseClicked() {
        this.host.nativeElement.remove();
    }

    // other code
}
Outsider
  • 1,166
  • 1
  • 14
  • 27
  • It works for me, but I don't know if this is the best practice – ptheodosiou Feb 10 '20 at 14:53
  • @ThPadelis I'm not sure whether this is the best practice either, but I am not aware of any drawbacks. Do you know where this will create issues? – Outsider Feb 11 '20 at 10:36
  • Not sure, have to test some things I got on my mind. I'll let you know if I found any issue – ptheodosiou Feb 11 '20 at 10:52
  • 1
    Any drawbacks for this solution ? I would like to use it (didn't find something better) :) – Joe Allen Jun 17 '20 at 14:25
  • 1
    @JoeAllen I've been using it. I haven't faced any yet. – Outsider Jun 18 '20 at 06:33
  • @ArkaGhosh I'm currently using it too because I didn't find something better. No problem at the moment – Joe Allen Jun 18 '20 at 15:26
  • 9
    It doesn't call "ngOnDestroy" if needed. And, if a listener is started with "HostListener" for example, it's not removed too. No automatic 'unsubscription'. – Doubidou Jul 06 '20 at 08:54
  • I've created a dialog component into which I can insert content externally. When I open and close and re-open the dialog I get all kinds of issues with icons not showing, invisible buttons remaining, form input elements not properly displaying. I've noticed this is due to the components I pass as content not being properly destroyed when the dialog is closed. Unfortunately, this isn't it, because it only removes the element from the DOM but doesn't end the component's life-cycle. – Otto Abnormalverbraucher Apr 22 '22 at 06:16
  • Why not calling the `ngOnDestroy` before the deletion ? – Raphaël Balet Apr 21 '23 at 13:42
17

Not sure about the cleanliness of such a solution, but I used:

this.viewContainerRef
    .element
    .nativeElement
    .parentElement
    .removeChild(this.viewContainerRef.element.nativeElement);
Sergiu Cosciug
  • 381
  • 3
  • 12
  • 7
    this is kinda hillarious, but does work and seems like a more proper answer than the accepted one. – phil294 Jun 14 '18 at 17:27
  • What to assign to viewContainerRef? – Mulperi Dec 07 '18 at 10:10
  • This does exactly what I needed. I needed a "Self Destruct" click on a component that had been instantiated in an *ngComponentOutlet and this did the trick! – httpete Jan 10 '19 at 05:09
  • If you import `ElementRef` you can do the following during `AfterViewInit` lifecycle: `this.element.nativeElement.parentNode.removeChild(this.element.nativeElement);` – David Meza Jan 10 '19 at 19:48
  • 11
    It'll make it disappear but the ngOnDestroy hook isn't called so isn't correct – creamcheese Oct 19 '19 at 12:23