Angular2 bootstrap modal with child component

3.4k views Asked by At

I would like to use Ng Bootstrap Modal with a child component as the modal body. I'm not sure how I would achieve this...

export class ParentComponent {
   @ViewChild("modal") private engineModal: TemplateRef<any>;
   dialog: NgbModalRef | null;

   constructor(private modalService: NgbModal) {}

   openModal(): void {
      this.dialog = this.modalService.open(this.engineModal);
   }

   cancelModal (): void {
      if ( this.dialog ) {
         this.dialog.dismiss();
         this.dialog = null;
      }
   }
}

and, I know this is wrong, but ultimately I'd like to do something like this,

<ng-template #modal>
  <app-child-component></app-child-component>
</ng-template>

Child component has a lot of Input and Output variables, so what whould be the best approach here?

3

There are 3 answers

6
Aravind On

You can project the content by passing it as a input property

<button class="btn btn-lg btn-outline-primary" (click)="open(element.innerHTML)">Launch demo modal</button>
<div #element style="display:none">>
  SOME THING PROJECTED
</div>

Your modal component should have the below modal-body

<div class="modal-body">
  <div [innerHTML]="modalBody">
  </div>
</div>

with the below input property

@Input() modalBody:string;

Update 1 : To change the values of @Input() property in the parent can be done as below,

setTimeout(()=>{
    this.modalRef.componentInstance.name = 'Opened After sometime';
},1000)

LIVE DEMO

0
Szkíta On

You may try content projection (transclusion for those familiar with AngularJS).

You can create a custom modal like this:

<div class="modal-body"> 
  <ng-content select="child-body"></ng-content>
</div>

And you create the child modal based on this custom-modal

<custom-modal>
  <child-body>
     {...}
  </child-body>
</custom-modal>

Basically what you write at between the child-body tags it will be copied in your custom-modal element at the ng-content's location.

Read more about content projection here:

https://angular-2-training-book.rangle.io/handout/components/projection.html

Hope this helps!

4
andrea06590 On

Hello yes you are right you have to use ViewChild to do this, then create an open function that use the open function as described :

open(engineModal) {
   console.log(this.engineModal) // global modal info from ViewChild
   console.log(engineModal) // modal info used for the function
   this.modalService.open(engineModal).result.then((result) => {
      this.closeResult = `Closed with: ${result}`;
   }, (reason) => {
   this.closeResult = `Dismissed ${this.getDismissReason(reason)}`;
});

See the .ts example https://ng-bootstrap.github.io/#/components/modal/examples

You simply have to do this, and you can now play with your modal

EDIT: To access your child component inside your ng-template : // bad way

@ViewChild(AppChildComponent) appChildComponent: AppChildComponent
this.engineModal.appChildComponent.function() 

=> I would personally encapsulate the ng-template inside the ModalInfoComponent, ModalNewsComponent html and use directly my answer ;)