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:
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:
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:
Now open up the index.html file and add the bootstrap 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:
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:
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:
2}
Not much there. Add in a constructor:
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:
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.
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:
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:
2 Modal Body
3</div>
Not much there, just some test text. Finally, add a 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:
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
2 }
Now, look at the onModalRequest() method:
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:
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:
2})
I started it empty. First, add the imports:
2 BrowserModule,
3 NgbModule.forRoot()
4 ],
It loads the BrowserM Now the declarations:
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:
Good to go!
And finally, add the PopupComponent the the entryComponents array:
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:
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.