Reusability is very important when programming, and anything we can do to reduce duplication of code is going to help us out.
I have to use Modal popups to display information to users in many places in my Angular 2 project. I am using ng-bootstrap and all of these Modals have the same Header and Footer but body changes in many cases. Sometimes the body just wanted to replace a single place holder, at other times it has some complexity to prepare the dynamic content. And these are triggered or managed by different components.
ng-bootstrap allow us to pass content into a Modal in two ways.
- as a Template. here wrap the whole Modal html in
<ng-template></ng-template> - as a Component
With the first approach, I have to write the header, body and footer repeatedly per modal.
With the second approach, I can wrap the HTML inside a component but need to put placeholders to make it dynamic. so then I can pass values as follows
open() {
const modalRef = this.modalService.open(NgbdModalContent);
modalRef.componentInstance.name = 'World';
}
But the flexibility is still limited.
What I am trying to achieve is to make a reusing modal component with Content Projection [Transclusion]
So, in my Common Modal's body looks as below. I placed <ng-content></ng-content> as a slot for the Modal's body.
@Component({
selector: 'common-modal',
template: `
<!-- Modal -->
<div class="modal fade" id="common-modal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">{{title}}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<ng-content></ng-content>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
`,
Now I wish I could use it as bellow.
<common-modal title="First Modal">
<span>Welcome Jasnan!</span>
</common-modal>
And at some other place
<common-modal title="Second Modal">
//......
<tr *ngFor="let student of pagedStudents">
<td>
{{student.name}}
</td>
<td>
{{student.grade}}
</td>
</tr>
//......
</common-modal>
How can I make this? Is there a way to do this in ng-bootstrap? Thanks for helping me to figure this out.