question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Modal Open Doesn't Support TemplateRef as Custom Component Passed from Template

See original GitHub issue

Bug description:

Modal open doesn’t support TemplateRef as custom component passed from template.

Initially I was expecting to use Modal something like this:

this.modalService.open(ModalWindowComponent, {
    body: EmployeeFormComponent,
    title: 'Employee',
    data: {
        age: 28
    }
});

with ModalWindowComponent template like this:

<div class="modal-dialog">
    <div class="modal-header">
        <h4 class="modal-title">{{modal.title}}</h4>
        <button type="button" class="close" aria-label="Close" (click)="modal.close()">
            <span aria-hidden="true">&times;</span>
        </button>
    </div>
    <div class="modal-body">
        <ng-template [ngTemplateOutlet]="modal.body">
            <!-- example: <app-employee-form></app-employee-form> -->
        </ng-template>
    </div>
</div>

But then I realized it’s impossible, or requires super complex logic with dynamic components creation. So, I decided to use recommended template-driven approach, having modal template in component template. But since I need custom body, I created ModalWindowComponent with this template:

<ng-template>
    <div class="modal-header">
        <h4 class="modal-title">{{title}}</h4>
        <button type="button" class="close" aria-label="Close" (click)="ref.dismiss()">
            <span aria-hidden="true">&times;</span>
        </button>
    </div>
    <div class="modal-body">
        <ng-content></ng-content>
    </div>
    <div class="modal-footer">
        <button type="button" class="btn btn-secondary" (click)="ref.close()">Cancel</button>
    </div>
</ng-template>

I was expecting to use it this way:

template
<button type="button" class="btn btn-primary" (click)="open(modal)">Open</button>
<app-modal-window [ref]="modal" [title]="'Title'" #modal>
    Body
</app-modal-window>
component
open(modal: NgbModalRef): void {
    this.modalService.open(modal).result.then((result: any) => {
        this.closeResult = `Closed with: ${result}`;
    }, (reason: any) => {
        this.closeResult = `Dismissed ${this.getDismissReason(reason)}`;
    });
}

But I see this error: No component factory found for [object Object]. Did you add it to @NgModule.entryComponents? I tried to fix it by adding ModalWindowComponent to entryComponents of related module, but it didn’t help.

However, this works:

<button type="button" class="btn btn-primary" (click)="open(modal)">Open</button>
<ng-template #modal let-c="close" let-d="dismiss">
    <div class="modal-header">
        <h4 class="modal-title">Title</h4>
        <button type="button" class="close" aria-label="Close" (click)="d()">
            <span aria-hidden="true">&times;</span>
        </button>
    </div>
    <div class="modal-body">
        Body
    </div>
    <div class="modal-footer">
        <button type="button" class="btn btn-secondary" (click)="c()">Cancel</button>
    </div>
</ng-template>

So, the question is what am I doing wrong? Maybe there’s a better way to achieve the desired behavior? I understand that Modal doesn’t support class-driven custom body component, but seems like I can’t get template-driven to work as well.

Link to minimally-working plunker that reproduces the issue:

https://angular-v6amvy.stackblitz.io

Version of Angular, ng-bootstrap, and Bootstrap:

Angular: 6.0.0

ng-bootstrap: 2.1.2

Bootstrap: 4.1.1

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:1
  • Comments:6 (1 by maintainers)

github_iconTop GitHub Comments

2reactions
pkozlowski-opensourcecommented, Jun 26, 2018

I guess the closest thing to what you are trying to do is shown here: https://stackblitz.com/edit/angular-v6amvy-pttrng?file=app/app.component.html

Closing as a support request.

0reactions
vickyRatheecommented, Mar 3, 2021

@souravsaraf @Halfist Did you find a solution to inject a component dynamically in the modal-body, I have a similar requirement and struggling to find a solution from from past few days. Here is my SO question - https://stackoverflow.com/questions/66434541/load-angular-component-dynamically-in-bootstrap-modal/66434970

Read more comments on GitHub >

github_iconTop Results From Across the Web

Angular ng-bootstrap Modal Open Doesn't Support ...
Angular ng-bootstrap Modal open doesn't support TemplateRef as custom component passed from template. Initially I was expecting to use Modal ...
Read more >
How to build a reusable Modal Overlay/Dialog Using Angular ...
Pass data as a String, Template or Component. Overlay Ref Class. We are going to start by extending the OverlayRef . We will...
Read more >
Angular ng-template, ng-container and ngTemplateOutlet
This is a Complete Guide To Angular Templates: it covers ng-template, ng-container, the ngTemplateOutlet structural directive, and more.
Read more >
Modal | NG-ZORRO
You can customize the buttons to the maximum extent by passing a ModalButtonOptions configuration (see the case or the instructions below). string TemplateRef...
Read more >
Modal - Angular powered Bootstrap
NgbModal. Service. A service for opening modal windows. Creating a modal is straightforward: create a component or a template and pass it as...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found