Modal with generic content in Angular app

Angular add a modal with generic content
Difficulty

Today we will see a way to add a modal with generic content in Angular, for web sites with many lists of resources, often even very complex.
We can handle it like another “page” in router, allowing every content we need in it.

This approach can be useful in cases where, for example, the contents should not completely obscure the list within the underlying page. In this way the user will always be able to return to the original page and will even be able to link the content of the modal.
Indeed the modal with its dynamic content will have its own route.

Core of the modal with generic content in Angular

Let’s create a component that will only wrap our content inside it.

modal.component.ts 💾

import { Component, EventEmitter, Input, Output } from '@angular/core';

@Component({
  selector: 'app-modal',
  templateUrl: './modal.component.html',
  /* Can add a custom style for the modal wrapper */
  styleUrls: ['./_modal.component.scss']
})
export class ModalComponent {
  @Input() visible: boolean;
  @Output() visibleChange: EventEmitter<boolean> = new EventEmitter<boolean>();

  constructor() {}

  close() {
    this.visibleChange.next(false);
    this.visible = false;
  }
}

modal.component.html 💾

<div *ngIf="visible" role="dialog" class="modal" tabindex="-1">
  <div [@modal] class="modal__inner def_back">
    <header class="modal__header">
      <button (click)="close()" class="modal__close" title="Close" 
          aria-label="Close modal">X</button>
    </header>
    <div class="modal__view">
      <ng-content></ng-content>
    </div>
  </div>
  <div (click)="close()" class="modal-background"></div>
</div>

We can append it in our root app template like a router “page”:

<router-outlet name="modal" id="container-modal"></router-outlet>

And then in our routing module we can add the two new paths:

app-routing.module.ts 💾

import { NgModule } from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
import {ModalItem1Component} from './components/modalItem1.component';
import {ModalItem2Component} from './components/modalItem2.component';

const routes: Routes = [{
    path: 'modal-item-1', 
    component: ModalItemOneComponent,
    outlet: 'modal'
  }, {
    path: 'modal-item-2',
    component: ModalItemTwoComponent,
    outlet: 'modal'
  }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule {
  constructor() {}
}

The components that will use this modal wrapper must only use the modal component wrapper.
The only needed function is the router close() function to close the modal.
One example:

modal-item-one.component.ts 💾 and modal-item-one.component. html 💾

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

@Component({
  selector: 'app-modal-item-one',
  templateUrl: './modal-item-one.component.html',
  /* Add a custom style for the single resource type */
  styleUrls: ['./_modal-item-one.component.scss']
})
export class ModalItemOneComponent {
  constructor(private _router: Router) {}

  close() {
    this._router.navigate([{ outlets: { modal: null } }]);
  }
}

Our example template will follow.

<app-modal [visible]="true" (visibleChange)="close()">
  <div #view>
    Add your particular content.
  </div>
</app-modal>

Open the modal with generic content in Angular

To finally call our modal we can define a button with the event (click) that, through the Router, navigates to the page within the modal itself.
In the template of the page that will call the modal we call the showModal() method which will perform the navigation inside the component.

<a (click)="showModal()" href="javascript:void(0);">
  Show modal
</a>
constructor(private _router: Router) {}

showModal() {
  this._router.navigate([{ outlets: { modal: ['modal-item-1'] } }]);
}

That’s all.
Try it at home.

0
Be the first one to like this.
Please wait...

2 thoughts on...
  1. I am genuinely thankful to the holder of this website who has shared this wonderful article at here. Ramona Leonard Giesecke

Leave a Reply

Thanks for choosing to leave a comment.
Please keep in mind that all comments are moderated according to our comment policy, and your email address will NOT be published.
Please do NOT use keywords in the name field. Let's have a personal and meaningful conversation.