How does one create a modal window with Bootstrap and Angular 4? This post will show you how.

The Setup

First, we need a generic app. You can use the Angular CLI, or my own seed project to create one. They are all going to give you a similar code base, although the directory structure is a bit different. I'm going to continue using the seed project I created, so you may have to make minor tweaks to the setup for other options.

Next be sure to install ng-bootstrap using Node:

view plain print about
1npm install --save @ng-bootstrap/ng-bootstrap

If using the Angular Quickstart or the DotComIt seed project, you'll have to tell SystemJS how to find it. Open the SystemJS config and add this to the map property:

view plain print about
1'@ng-bootstrap/ng-bootstrap': 'js:@ng-bootstrap/ng-bootstrap/bundles/ng-bootstrap.js'

The seed project scripts will need to copy the Bootstrap libraries into the build directory. Just find the angularLibraries array in the config.js file and add the new entry:

view plain print about
1'@ng-bootstrap/ng-bootstrap/bundles/ng-bootstrap.js'

Now open up the index.html file and add the bootstrap CSS:

view plain print about
1<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" />

Create the Pop Component

Now, let's create a component that will be the popup. Create a file named popup.component.ts in src/com/dotComIt/learnWith/views/popup. First, add your imports:

view plain print about
1import {Component} from '@angular/core';
2import {NgbActiveModal} from "@ng-bootstrap/ng-bootstrap";

This imports the Component so we can create this class as a component. It also imports the NgbActiveModal. This will allow us to close the modal.

Create the @Component metadata:

view plain print about
1@Component({
2 selector: 'Popup',
3 templateUrl : './com/dotComIt/learnWith/views/popup/popup.component.html',
4 styleUrls: [ './com/dotComIt/learnWith/views/popup/popup.component.css' ]
5})

I named the selector Popup, although we won't need that. I also specified an external HTML template and an external CSS file. I do this as a matter of habit. The CSS file can be empty. We'll roll back to the HTML file in a bit. For now, create the class:

view plain print about
1export class PopupComponent {
2}

Not much there. Add in a constructor:

view plain print about
1constructor(public activeModal: NgbActiveModal) {
2 }

The constructor will inject an instance of the NgbActiveModal class into this component using Angular's Dependency Injection syntax.

Finally, we'll add two methods. The first is to close the popup:

view plain print about
1onClose():void {
2 this.activeModal.close('closed');
3 }

Closing the popup usually means the user is done interacting with it and wants to move on to other things.

view plain print about
1onDismiss(reason : String):void {
2 this.activeModal.dismiss(reason);
3 }

Dismissing the popup means the user is cancelling the operation. Both methods will be referenced inside the HTML template. Overall there is not much to this Angular Component, because I left it simple for sample purposes. It could get as complex as you need it to.

Now look at the popup.component.html file. Start with a header:

view plain print about
1<div class="modal-header">
2 <h4 class="modal-title">Test Modal</h4>
3 <button type="button" class="close" aria-label="Close" (click)="onDismiss('Cross click')">
4 <span aria-hidden="true">x</span>
5 </button>
6</div>

The header includes a Title and an X button. When the X button is clicked, the onDismiss() method is called. Dismissing the modal is like cancelling it, whereas closing it usually means you are done with it.

Now, add a body:

view plain print about
1<div class="modal-body">
2 Modal Body
3</div>

Not much there, just some test text. Finally, add a footer:

view plain print about
1<div class="modal-footer">
2 <button class="btn btn-primary" type="button" (click)="onDismiss('Close click')">Cancel</button>
3 <button class="btn btn-warning" type="button" (click)="onClose()">Close</button>
4</div>

The footer includes two buttons. One is a cancel button which will dismiss the modal. The other is a close button. Both call the related methods inside the component.

That's all we need to create the component that will display inside the modal.

Modify the Main App Component

Open up the app.component.ts file. Modify the template to be like this:

view plain print about
1template : '<button (click)="onModalRequest()">Open Modal</button>'

There is a single button which will call an onModalRequest() function. The onModalRequest() function goes in the class body of the AppComponent. But, first be sure that the constructor injects ng-bootstrap's NgbModal

view plain print about
1constructor(private modalService: NgbModal) {
2 }

Now, look at the onModalRequest() method:

view plain print about
1onModalRequest():void {
2 const modalRef = this.modalService.open(PopupComponent );
3
4 modalRef.result.then((result) =>
{
5 console.log(result);
6 console.log('closed');
7 }).catch( (result) => {
8 console.log(result);
9 console.log('cancelling');
10 });
11 }

First, the modalRef is created using the mmodalService.open() method. The PopupComponent is sent in as an argument, so be sure to import it. The modalRef.result is a promise object. If the modal is closed then the result function will be executed. If it is dismissed the failure function will execute. For both of these functions, I'm just outputting the results to the log. /

Modify the app.module

We need to tell the @NgModule about the popup component. First, review the imports:

view plain print about
1import { NgModule } from '@angular/core';
2import { BrowserModule } from '@angular/platform-browser';
3
4import {NgbModule} from '@ng-bootstrap/ng-bootstrap';
5
6import { AppComponent } from './app.component';
7import {PopupComponent} from "../views/popup/popup.component";

The first two imports are from the angular library. The second one comes from the ng-bootstrap library. The final two imports related to our custom code.

Create the NgModule metadata:

view plain print about
1@NgModule({
2})

I started it empty. First, add the imports:

view plain print about
1imports: [
2 BrowserModule,
3 NgbModule.forRoot()
4 ],

It loads the BrowserM

Now the declarations:

view plain print about
1declarations: [
2 AppComponent,
3 PopupComponent
4 ],

The declarations tells the module which of our custom components need to be ready for use.

Next, bootstrap our app's main component:

view plain print about
1bootstrap: [ AppComponent ],

Good to go!

And finally, add the PopupComponent the the entryComponents array:

view plain print about
1entryComponents: [PopupComponent]

This is important because this is how we tell Angular to allow this component instance to be created on the fly with our code.

Finally, after the metadata, export the component class:

view plain print about
1export class AppModule { }

Test It

Now you can test things. Open the app in a browser:

Now, click the Open Modal button:

Click the X or Cancel Button. You should see a message show up in the console:

Open it again, and click the close button:

You are good to go. I wrote this post as a prelude to testing Bootstrap Popups with Angular. Those articles will come over the next few weeks. In the meantime, get my new book series on Angular 4 which uses similar techniques.

Keep up to date by reading DotComIt's Monthly Technical Newsletter