akko
akko

Reputation: 639

How can I destroy an Angular component?

I'm making a modal and I made it a component <modal-component>.

Inside <modal-component> I have a close button. I want to destroy <modal-component> when I click that button.

Something like this:

<button (click)="closeModal()">Close</button>

I also could make the close button a component. Something like <close-modal> if neccesary.

Is this possible?

Upvotes: 7

Views: 21786

Answers (4)

Felix
Felix

Reputation: 1810

There is one other trick:

import { ViewContainerRef } from '@angular/core';

constructor(private viewContainerRef: ViewContainerRef) {}
...
private selfClose() {
   this.viewContainerRef
    .element
    .nativeElement
    .parentElement
    .removeChild(this.viewContainerRef.element.nativeElement);
}

NOTE: It'll make the component removed / disappear, but the ngOnDestroy hook isn't called, the component is NOT fully destroyed until the parent is destroyed.

Upvotes: 2

Adrian Brand
Adrian Brand

Reputation: 21658

Create a ModalControlService that has a boolean BehaviorSubject

import { Injectable } from '@angular/core';

import {BehaviorSubject} from 'rxjs';

@Injectable()
export class ModalControlService {
  modalOpen$ = new BehaviorSubject<boolean>(false);

  open() {
    this.modalOpen$.next(true);
  }

  close() {
    this.modalOpen$.next(false);
  }
}

Provide the service from the component you want to host the modal from so you get the same instance of the service in your host component and your modal component.

In the host component

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

import { ModalControlService } from './modal-control.service';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ],
  providers: [ ModalControlService ]
})
export class AppComponent  {
  modalOpen$ = this.modalControlService.modalOpen$;

  constructor(private modalControlService: ModalControlService) {}

  openModal() {
    this.modalControlService.open();
  }
}

and in the template

<modal-component *ngIf="modalOpen$ | async"></modal-component>

Then in the modal component

import { Component, OnInit } from '@angular/core';

import { ModalControlService } from '../modal-control.service';

@Component({
  selector: 'modal-component',
  templateUrl: './modal.component.html',
  styleUrls: ['./modal.component.css']
})
export class ModalComponent {

  constructor(private modalControlService: ModalControlService) { }

  closeModal() {
    this.modalControlService.close();
  }
}

StackBlitz https://stackblitz.com/edit/angular-gc1ugw?file=src%2Fapp%2Fapp.component.ts

Upvotes: 3

Aravind
Aravind

Reputation: 41581

If you are using ngx-bootstrap modal dialog, by default the component is destroyed on close

Typescript

openModal() {
this.modalRef = this.modalService.show(SomeComponent,  {
  initialState: {
    title: 'Modal title',
    data: {}
  }
});
}

HTML

<div (click)="openModal()" class="btn btn-success"> Modal Component</div>

Stackblitz

Upvotes: 1

Roberto Zvjerković
Roberto Zvjerković

Reputation: 10157

Parent must destroy its child. So you can send an event from child

@Output()
onClose: EventEmitter<boolean> = new EventEmitter();

...
closeModal() {
    this.onClose.emit(true);
}

And capture the event in parent:

<modal-component *ngIf="showModal" (onClose)="modalClosed($event)">

And parent component:

modalClosed(isClosed) {
    this.showModal = false;
}

*ngIf directive will take care of the rest.

Might be a mistake or two, I'm on a mobile...

Upvotes: 6

Related Questions