Published on

How to display a modal in Angular 10

History Screen
Figure 1: An example of a modal

Web design in the modern age uses modals extensively! What is a modal, you ask? A modal is a window that is subordinate to an application’s main window. Modals creates a scenario where the main window is temporarily disabled and the focus to diverted to the modal window, which is positioned in front of the main window. How would we implement a modal window using the popular web application framework Angular? Just keep reading to find out!

Prerequisite:

To follow along in this tutorial you will need an Angular project. I will be starting a new Angular project from scratch so just follow along! If you ever need to look at the source code because of unexpected bugs, you can find it on my GitHub repo.

First we need to use a Terminal instance in an IDE. I highly recommend using Visual Studio Code, which what I will use in this tutorial.

History Screen
Figure 2: Open a Terminal instance in VS Code

Now we will create the Angular project folder and cd into it via:

ng new modal-tutorial
cd modal-tutorial

Now we will have to add the Angular Material library to our Angular project. We do this by running:

ng add @angular/material

Running the above command will bring up a prompt that allows you to choose the theme, whether or not you want to setup HammerJS, and setup browser animations. The choice of theme is entirely up to you but make sure to not setup HammerJS. Finally, make sure you setup browser animations for Angular Material by selecting ‘Y’ when you’re prompted to.

History Screen
Figure 3: Please make sure you choose ‘Y’ for browser animations!

Congrats! Angular Material is setup in your project now. Next, we will create the modal component. Let’s call it projects-modal, in order to have some relevancy to what we will build:

ng generate component projects-modal

The modal will display a list of software development projects when it is click on, so the name projects-modal would be appropriate.

At this point we have to add the project-modal component to the @NgModule in the app.module.ts file like so:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

import { MatButtonModule } from '@angular/material/button';
import { MatDialogModule } from '@angular/material/dialog';
import { ProjectsModalComponent } from './projects-modal/projects-modal.component';

@NgModule({
  declarations: [
    AppComponent,
    ProjectsModalComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    BrowserAnimationsModule,
    MatButtonModule,
    MatDialogModule
  ],
  providers: [],
  bootstrap: [AppComponent],
  entryComponents: [ProjectsModalComponent]
})
export class AppModule { }

Note that we first import the ProjectsModalComponent then add it to the declarations and entryComponents sections.

You might be wondering why we need to add ProjectsModalComponent to both declarations and entryComponents. This is because in order to make directives from the current module available to other directives ProjectsModalComponent would have to be included in declarations. The entryComponents section is used to define only components that are not found in html and created dynamically with ComponentFactoryResolver. Since ProjectsModalComponent falls into this category, it would have to be included in the entryComponents

App Component

Now let’s code the app component’s view a.k.a app.component.html:

<main id="show-projects-button-holder">
  <button mat-raised-button id="show-projects-button" (click)="openModal()">Show Projects</button>
</main>

This will ensure that the user sees a mainly blank screen with only a button in it. The button click will be used to open the modal. Take note of the mat-raised-button attribute in the button tag because it changes the button from being a plain old html element into an Angular Material button.

Now we need to add some logic to the typescript file of the app component. This will allow the app component to process when to show open the modal and when to close it. Here is the code for app.component.ts:

import { Component } from '@angular/core';

import { MatDialog, MatDialogConfig, MatDialogRef } from '@angular/material/dialog';
import { ProjectsModalComponent } from './projects-modal/projects-modal.component';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent {
  dialogConfig = new MatDialogConfig();
  modalDialog: MatDialogRef<ProjectsModalComponent, any> | undefined;
  constructor(public matDialog: MatDialog) { }

  ngAfterViewInit(): void {
    document.onclick = (args: any) : void => {
          if(args.target.tagName === 'BODY') {
              this.modalDialog?.close()
          }
      }
  }

  openModal() {

    this.dialogConfig.id = "projects-modal-component";
    this.dialogConfig.height = "500px";
    this.dialogConfig.width = "650px";
    this.modalDialog = this.matDialog.open(ProjectsModalComponent, this.dialogConfig);
  }
}

The dialogConfig and modalDialog variables are the what holds the instance of ProjectsModalComponent and displays it to the screen. The constructor uses dependency injection to inject the matDialog variable with the MatDialog service.

The NgAfterViewInit method is used to close the modal if the user clicks anything other than the modal itself, on the browser window.

Finally, the openModal method opens the modal window in front of the main browser window, while assigning it a specific height, width and id value. The id value will be used to assign CSS styles to the modal window. In case you’re curious click here for the official documentation on the MatDialog.open method on the Angular Material website.

It’s time to add the html for the the modal component in the projects-modal.component.html file:

<div id="modal-content-wrapper">
    <header id="modal-header">
        <h1 id="modal-title">Project List</h1>
    </header>
    <ul>
        <li>FTP Program Application</li>
        <li>Image to Text Converter Application</li>
        <li>Library Management System</li>
        <li>Image fetching API</li>
        <li>Quiz Game Application</li>
    </ul>
    <footer id="modal-footer">
        <button mat-raised-button id="modal-close-button" (click)="closeModal()">Close</button>
    </footer>
</div>

Note that the list items inside the unordered list is not significant in anyway, it’s just dummy text. Also, notice the click event listener on the Close Modal button that will execute the closeModal method once clicked on.

Adding the closeModal method to the projects-modal.component.ts file can be done now so let’s do it:

import { Component, OnInit } from '@angular/core';
import { MatDialogRef } from '@angular/material/dialog';

@Component({
  selector: 'app-projects-modal',
  templateUrl: './projects-modal.component.html',
  styleUrls: ['./projects-modal.component.css']
})
export class ProjectsModalComponent implements OnInit {

  constructor(public dialogRef: MatDialogRef<ProjectsModalComponent>) { }

  ngOnInit(): void {
  }

  closeModal() {
    this.dialogRef.close();
  }
}

After this, we need to add the CSS styles for the modal component in the projects-modal.component.css file like so:

#modal-content-wrapper {
    width: 100%;
    height: 100%;
    display: grid;
    grid-template-rows: repeat(1fr, 3);
}

#modal-title {
    font-size: 22px;
}

#modal-footer {
    justify-self: right;
    align-self: center;
}

#modal-close-button {
    background-color: #ce0909;
}

These styles will center the modal on the main window and give the Close button a reddish background color.

An important point to mention is that although the #modal-content-wrapper div encapsulates the modal content, it is not the main container div of the modal window. That role is full-filled by the dialogConfig variable in the app.component.ts file. If you recall, we added this line of code to app.component.ts:

this.dialogConfig.id = "projects-modal-component";

So the div with the id attribute set to projects-modal-component will be the actually container for the modal window. Interestingly enough, we cannot set the CSS styles for div#projects-modal-component in the modal component itself because the modal component only contains the contents of the modal, not the actual modal container div.

To add the neccessary CSS styles to the actual modal container we will need use the global CSS file: styles.css. Let’s add the following styles to styles.css:

html, body {
    height: 100%;
}

body {
    margin: 0;
    font-family: Arial, Helvetica, sans-serif;
    display: grid;
    justify-items: center;
    align-items: center;
    background-color: #fcfcfc;
}

mat-dialog-container#projects-modal-component {
    border: 3px solid #262626;
    border-radius: 11px;
    background-color: #e4d8d8;
}

#show-projects-button {
    color: white;
    background-color: #d80c0c;
    border: 1px solid black;
}

For the above CSS styles, the first two styles are pretty self-explanatory. They give a 100% height and white background color to the main window while centering the Show Projects button to the middle of the window.

Next come the styles for the modal window container div, which give it a rounded black border and a beige background color, along with the Show Projects button’s styles that give it a red background color.

History Screen
Figure 4: This is what our modal window looks like!

That should conclude the coding for this project. To run the project enter the command:

npm start

If you run into any issues please feel free to look at the source code for this application on my GitHub repo by clicking here.

Conclusion

Well that’s all for today, I hope you found this article helpful. Thanks so much for reading my article! Feel free to follow me on Twitter and GitHub, connect with me on LinkedIn and subscribe to my YouTube channel.