Published: May 25 2018

Angular 6 - Custom Modal Window / Dialog Box

Built with Angular 6.1.10 and Webpack 4.30.0

Other versions available:

In this tutorial we'll cover how to implement modal windows (dialog boxes) in Angular 6 with TypeScript. The example is a custom modal without the need for any 3rd party libraries.

The tutorial code is available on GitHub at

There are plenty of 3rd party libraries and plugins out there that include modal windows, and up until recently I used them myself when I needed to add a modal to a project. The main issue that I have with 3rd party libraries is that they usually contain a lot of features I don't need which adds unnecessary bloat to my application, so a while back I took the time to create a custom modal window in Angular 1 to see how difficult it would be and also to remove the mystery I had in my mind about exactly how modals work.

Once I'd finished I was surprised at the relatively small amount of code required to implement a custom modal window, most of the modal 'magic' is done with a handful of css styles (see the modal.less file) while TypeScript is just used for showing and hiding the modal windows.

Here it is in action: (See on StackBlitz at

Update History:
  • 16 Apr 2019 - Updated to Angular 6.1.10 and Webpack 4.30.0
  • 25 May 2018 - Built with Angular 6.0.3 and Webpack 4.8.1

Running the Angular 6 Modal Example Locally

  1. Install NodeJS and NPM from
  2. Download or clone the project source code from
  3. Install all required npm packages by running npm install from the command line in the project root folder (where the package.json is located).
  4. Start the application by running npm start from the command line in the project root folder.

Angular 6 Custom Modal Setup

There are three main pieces of code that make up this custom modal implementation:

  • Modal LESS/CSS styles in /src/app/_content/modal.less
  • Angular 6 Modal Service in /src/app/_services/modal.service.ts
  • Angular 6 Modal Directive in /src/app/_directives/modal.component.ts

Adding an Angular 6 Modal Dialog to your page

Once you have the above three files (or the code from them) integrated into your project, you can add modals to your pages with the custom <jw-modal> tag like this:

<jw-modal id="custom-modal-1">
    <h1>A Custom Modal!</h1>
    <p>Home page text: <input type="text" [(ngModel)]="bodyText" /></p>
    <button (click)="closeModal('custom-modal-1');">Close</button>

A unique id is required for each modal on a page, this is passed to the modal service from your controller to identify which modal to open/close.

You can put any content you want within the <jw-modal> element, you could also update the modal LESS/CSS if you want to change the styles of the modals, e.g to make them smaller or add CSS transitions etc. By default modals are closed on background click, to disable this remove the chunk of code in modal.component.ts located directly below the comment // close modal on background click.

Opening & Closing Angular 6 Modal Dialogs

To open and close (show/hide) a modal dialog you need to use an instance of the ModalService by importing it into your controller, injecting it into the constructor and calling and this.modalService.close(), e.g:

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

import { ModalService } from '../_services';

@Component({ templateUrl: 'home.component.html' })
export class HomeComponent implements OnInit {
    private bodyText: string;

    constructor(private modalService: ModalService) {

    ngOnInit() {
        this.bodyText = 'This text can be updated in modal 1';

    openModal(id: string) {;

    closeModal(id: string) {

The example controller passes the modal id from the view, but it could also be set directly in the controller like this:'my-custom-modal');

The view then calls the methods exposed by the controller in the usual way:

<div class="col-md-6 col-md-offset-3">
    <button (click)="openModal('custom-modal-1')">Open Modal 1</button>
    <button (click)="openModal('custom-modal-2')">Open Modal 2</button>


Breakdown of the Angular 6 Custom Modal Code

Below is a breakdown of the pieces of code used to implement custom modal dialogs in Angular 6, you don't need to know the details of how it all works to use the modals in your project, it's only if you're interested in the nuts and bolts or if you want to modify the code or behaviour.

LESS/CSS Styles for Angular 6 Modal Dialogs

These are the styles applied to the custom modal dialogs in this example, they could also be used in non-angular projects as it's just pure LESS/CSS.

I prefixed the modal element and classes with jw- to prevent conflicts with 3rd party css libraries such as Bootstrap.

jw-modal {
    /* modals are hidden by default */
    display: none;

    .jw-modal {
        /* modal container fixed across whole screen */
        position: fixed;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;

        /* z-index must be higher than .jw-modal-background */
        z-index: 1000;
        /* enables scrolling for tall modals */
        overflow: auto;

        .jw-modal-body {
            padding: 20px;
            background: #fff;

            /* margin exposes part of the modal background */
            margin: 40px;

    .jw-modal-background {
        /* modal background fixed across whole screen */
        position: fixed;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;

        /* semi-transparent black  */
        background-color: #000;
        opacity: 0.75;
        /* z-index must be below .jw-modal and above everything else  */
        z-index: 900;

body.jw-modal-open {
    /* body overflow is hidden to hide main scrollbar when modal window is open */
    overflow: hidden;

Angular 6 Modal Service

The modal service manages the communication that's required between angular 6 controllers and modal directive instances. It maintains a current list of available modals on the page and exposes methods for interacting with those modals.

export class ModalService {
    private modals: any[] = [];

    add(modal: any) {
        // add modal to array of active modals

    remove(id: string) {
        // remove modal from array of active modals
        this.modals = this.modals.filter(x => !== id);

    open(id: string) {
        // open modal specified by id
        let modal: any = this.modals.filter(x => === id)[0];;

    close(id: string) {
        // close modal specified by id
        let modal: any = this.modals.filter(x => === id)[0];

Angular 6 Modal Directive Component

The custom modal directive is used for adding modals anywhere in your angular application by using the <jw-modal> tag. Each modal instance registers itself with the ModalService when it loads using the ngOnInit lifecycle hook, and removes itself from the ModalService when it's destroyed using the ngOnDestroy lifecycle hook.

import { Component, ElementRef, Input, OnInit, OnDestroy } from '@angular/core';

import { ModalService } from '../_services';

    selector: 'jw-modal',
        `<div class="jw-modal">
            <div class="jw-modal-body">
        <div class="jw-modal-background"></div>`

export class ModalComponent implements OnInit, OnDestroy {
    @Input() id: string;
    private element: any;

    constructor(private modalService: ModalService, private el: ElementRef) {
        this.element = el.nativeElement;

    ngOnInit(): void {
        let modal = this;

        // ensure id attribute exists
        if (! {
            console.error('modal must have an id');

        // move element to bottom of page (just before </body>) so it can be displayed above everything else

        // close modal on background click
        this.element.addEventListener('click', function (e: any) {
            if ( === 'jw-modal') {

        // add self (this modal instance) to the modal service so it's accessible from controllers

    // remove self from modal service when directive is destroyed
    ngOnDestroy(): void {

    // open modal
    open(): void { = 'block';

    // close modal
    close(): void { = 'none';


Need Some Angular 6 Help?

Search fiverr for freelance Angular 6 developers.

Follow me for updates

On Twitter or RSS.

When I'm not coding...

Me and Tina are on a motorcycle adventure around Australia.
Come along for the ride!


Supported by