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?

3
  • you want to pass the body dynamically? Commented Dec 12, 2017 at 18:45
  • yes, that pretty much sums up what I would like to do Commented Dec 12, 2017 at 18:51
  • 1
    Go to ng-bootstrap.github.io/#/components/modal/examples, and look at the second example, "Components as content". Commented Dec 12, 2017 at 18:56

3 Answers 3

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!

Sign up to request clarification or add additional context in comments.

Comments

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

4 Comments

Well, I don't think this works tho, I'm trying to load the modal dynamically, and it's using the ng template.....
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 ?
I think that would be the best way, what do you mean by encapsulating the ng-template inside the component?
I mean you create your component with your input, output... and inside you'll have your ng-template ;) like this <app-modal-info (open)="open()" [title]="My title"> <ng-template #modal>specific html goes here</ng-template> </app-modal-info>
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

6 Comments

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
by load the child component what you mean ? can you explain
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 so you don't want to load the modal dynamically?
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
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.