1

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?

PowerLove
  • 303
  • 8
  • 25

3 Answers3

1

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!

Szkíta
  • 161
  • 1
  • 8
0

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 ;)

andrea06590
  • 1,259
  • 3
  • 10
  • 22
  • Well, I don't think this works tho, I'm trying to load the modal dynamically, and it's using the ng template..... – PowerLove Dec 12 '17 at 19:02
  • What about encapsulating you ng-template inside your own component ? Then you can have access to your component and the modal. So that you can rewrite the behavior of your child modal. is that what you need ? – andrea06590 Dec 12 '17 at 19:55
  • I think that would be the best way, what do you mean by encapsulating the ng-template inside the component? – PowerLove Dec 12 '17 at 20:27
  • I mean you create your component with your input, output... and inside you'll have your ng-template ;) like this specific html goes here – andrea06590 Dec 12 '17 at 21:16
0

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

Aravind
  • 40,391
  • 16
  • 91
  • 110
  • Yes, I agree, but I was just wondering if there's a way to load the child component since child component has interactions with the parent – PowerLove Dec 12 '17 at 19:06
  • by `load the child component` what you mean ? can you explain – Aravind Dec 12 '17 at 19:11
  • Seems like I'm having to create a modal component. I mean which is fine, but then I already have child component defined where it takes about 12 inputs from parent component and have 4 eventemitter outputs. I can have them go through the modal component, but I'm wondering if there's any other way – PowerLove Dec 12 '17 at 19:49
  • @PowerLove so you don't want to load the modal dynamically? – Aravind Dec 12 '17 at 19:53
  • I guess I kinda left out a lot of details in the question... I'm sorry, so the variables in the parent component dynamically changes, which changes the inputs in the child component – PowerLove Dec 12 '17 at 19:59
  • @PowerLove it will work if the variables are changed also – Aravind Dec 12 '17 at 20:08