Show/Hide Dialog Or Modal Service In Angular

Introduction

 
In this article we will see how to create a modal window or dialog box in Angular. We will use Angular and typescript to show or hide the modal window.
 
We will be using NgbModal in order to open the modal. This is just required to create a component and pass the template in its open method.
 
This also have a Dismiss method for closing the modal with the particular reason.
 
Let’s start creating the application with the dialog service provided on a specified event.
 
We will modify the existing application to add the Dialog functionality.
 
 
Where to apply the modal dialog?
  1. We will try to show the dialog if User is clicking on “Register” button without filling the fields.
  2. We will try to show the dialog if the User that you are trying to register is already present.
  3. We will show dialog if the user is successfully created.
We will be using RXJS Subject in order to achieve the dialog service. Subject is a special type of observable that allow values to multicast to many observers.
 
Create a modal.service.ts in _services directory and add the below content:
  1. import { Injectable } from '@angular/core';  
  2. import { NgbModal, ModalDismissReasons } from '@ng-bootstrap/ng-bootstrap';  
  3.   
  4. @Injectable({  
  5.   providedIn: 'root'  
  6. })  
  7. export class ModalService {  
  8.     closeResult = '';  
  9.   
  10.     constructor(private modalService: NgbModal){}  
  11.   
  12.     open(content) {  
  13.         return this.modalService.open(content, {ariaLabelledBy: 'modal-basic-title'})  
  14.         .result.then((result) => {  
  15.         return this.closeResult = `Closed with: ${result}`;  
  16.       }, (reason) => {  
  17.         return this.closeResult = `Dismissed ${this.getDismissReason(reason)}`;  
  18.       });  
  19.     }  
  20.     
  21.     private getDismissReason(reason: any): string {  
  22.       if (reason === ModalDismissReasons.ESC) {  
  23.         return 'by pressing ESC';  
  24.       } else if (reason === ModalDismissReasons.BACKDROP_CLICK) {  
  25.         return 'by clicking on a backdrop';  
  26.       } else {  
  27.         return `with: ${reason}`;  
  28.       }  
  29.     }  

Create dialog.service.ts in _services directory and add the below contents:
  1. import { Injectable } from '@angular/core';  
  2. import { Observable, Subject } from 'rxjs';  
  3.   
  4. @Injectable({ providedIn: 'root' })  
  5. export class DialogService {  
  6.     private dialogSubject = new Subject<any>();  
  7.       
  8.     sendDialog(dialog: {type: number, message: string}) {  
  9.         this.dialogSubject.next(dialog);  
  10.     }  
  11.   
  12.     clearDialog() {  
  13.         this.dialogSubject.next();  
  14.     }  
  15.   
  16.     getDialog(): Observable<any> {  
  17.         return this.dialogSubject.asObservable();  
  18.     }  
  19. }  
  20.   
  21. Create page.service.ts in _services and add below contents:  
  22. import { Injectable } from '@angular/core';  
  23. import { Observable, Subject } from 'rxjs';  
  24.   
  25. @Injectable({ providedIn: 'root' })  
  26. export class PageService {  
  27.     private pageSubject = new Subject<any>();  
  28.       
  29.     sendPage(dialog: {type: number, message: string}) {  
  30.         this.pageSubject.next(dialog);  
  31.     }  
  32.   
  33.     clearPage() {  
  34.         this.pageSubject.next();  
  35.     }  
  36.   
  37.     getPage(): Observable<any> {  
  38.         return this.pageSubject.asObservable();  
  39.     }  

Let’s create a component that will have the templates for opening the dialog content.
 
Create _component directory in app directory.
 
Create component prompt inside _component directory.
 
Open prompt.component.ts
  1. import { Component, OnInit, Input, ViewChild, ElementRef } from '@angular/core';  
  2. import { ModalService } from 'src/app/_services/modal.service';  
  3. import { DialogService } from 'src/app/_services/dialog.service';  
  4. import { Subscription } from 'rxjs';  
  5. import { PageService } from 'src/app/_services/page.service';  
  6.   
  7. @Component({  
  8.   selector: 'app-prompt',  
  9.   templateUrl: './prompt.component.html',  
  10.   styleUrls: ['./prompt.component.css']  
  11. })  
  12. export class PromptComponent implements OnInit {  
  13.   @Input() result: number;  
  14.   subscription: Subscription;  
  15.   @ViewChild('dialog_required') dialog_required: ElementRef;  
  16.   @ViewChild('dialog_serverError') dialog_serverError: ElementRef;  
  17.   @ViewChild('dialog_success') dialog_success: ElementRef;  
  18.   
  19.   closeResult = '';  
  20.   serverError = '';  
  21.   serverResponse = '';  
  22.   
  23.   constructor(private modalService: ModalService, private dialogService: DialogService, private pageService: PageService) {  
  24.     this.result = 0;  
  25.     this.subscription = this.dialogService.getDialog().subscribe(dialog => {  
  26.       if (dialog) {  
  27.         this.open(dialog);  
  28.       }  
  29.     });  
  30.   }  
  31.   
  32.   open(dialogType) {  
  33.     switch(dialogType.type)  
  34.     {  
  35.         case 1:  
  36.           this.modalService.open(this.dialog_required).then(data=>{  
  37.             this.closeResult = data;  
  38.           });  
  39.            break;  
  40.         case 2:  
  41.           this.serverError = dialogType.message;  
  42.           this.modalService.open(this.dialog_serverError).then(data=>{  
  43.             this.closeResult = data;              
  44.           });  
  45.           break;  
  46.         case 3:  
  47.           this.serverResponse = dialogType.message;  
  48.           this.modalService.open(this.dialog_success).then(data=>{  
  49.             this.closeResult = data;          
  50.             this.pageService.sendPage({type: 1, message: "page"})      
  51.           });  
  52.           break;  
  53.         default:  
  54.           console.log('no modal opens');  
  55.     }     
  56.   }   
  57.   
  58.   ngOnInit(): void {  
  59.     console.log(this.result)  
  60.   }  
  61.   
  62.   ngOnDestroy() {  
  63.     // unsubscribe to ensure no memory leaks  
  64.     this.subscription.unsubscribe();  
  65.   }  

Open prompt.comonent.html and add the below contents:
  1. <ng-template #dialog_required let-modal>  
  2.   <div class="card-header" style="background-color:cyan;">  
  3.     <h4>  
  4.       Error  
  5.     <button type="button" class="close" aria-label="Close" (click)="modal.dismiss('Cross click')">  
  6.       <span aria-hidden="true">×</span>  
  7.     </button>  
  8.     </h4>  
  9.   </div>  
  10.   <div class="modal-body" style="background-color:lightsteelblue">  
  11.     <label>Required fields must be filled!</label>  
  12.   </div>  
  13. </ng-template>  
  14.   
  15.   <ng-template #dialog_serverError let-modal>  
  16.     <div class="card-header" style="background-color:cyan;">  
  17.       <h4>  
  18.         Error  
  19.       <button type="button" class="close" aria-label="Close" (click)="modal.dismiss('Cross click')">  
  20.         <span aria-hidden="true">×</span>  
  21.       </button>  
  22.       </h4>  
  23.     </div>  
  24.     <div class="modal-body" style="background-color:lightsteelblue">  
  25.       <label>{{serverError}}</label>  
  26.     </div>  
  27.   </ng-template>  
  28.   
  29.   <ng-template #dialog_success let-modal>  
  30.     <div class="modal-header" style="background-color:cyan;">  
  31.       <h4 class="modal-title" id="modal-basic-title">Success</h4>  
  32.       <button type="button" class="close" aria-label="Close" (click)="modal.dismiss('Cross click')">  
  33.         <span aria-hidden="true">×</span>  
  34.       </button>  
  35.     </div>  
  36.   
  37.     <div class="modal-body" style="background-color:lightsteelblue">  
  38.       <form>  
  39.         <div class="form-group">  
  40.           <label for="serverResponse">{{serverResponse}}</label>  
  41.         </div>  
  42.       </form>  
  43.     </div>  
  44.   
  45.     <div class="modal-footer" style="background-color:lightsteelblue">  
  46.       <button type="button" class="btn btn-outline-dark" (click)="modal.close('Save click')">Ok</button>  
  47.     </div>  
  48.   </ng-template> 
Open Register.component.ts and add the below contents:
  1. import { Component, OnInit } from '@angular/core';  
  2. import { AuthService } from '../_services/auth.service';  
  3. import { User } from '../_model/user';  
  4. import { Router } from '@angular/router';  
  5. import { DialogService } from '../_services/dialog.service';  
  6. import { Subscription } from 'rxjs';  
  7. import { PageService } from '../_services/page.service';  
  8.   
  9. @Component({  
  10.   selector: 'app-register',  
  11.   templateUrl: './register.component.html',  
  12.   styleUrls: ['./register.component.css']  
  13. })  
  14. export class RegisterComponent implements OnInit  {  
  15.   
  16.   component: any;  
  17.   subscription: Subscription;  
  18.   registerResult: number = 0;  
  19.   registerUserData = new User();  
  20.   constructor(private _authservice: AuthService, private router: Router, private dialogService: DialogService,private pageService: PageService) {    
  21.     // redirect to home if already logged in  
  22.       if (this._authservice.currentUserValue) {   
  23.         this.router.navigate(['/paidevents']);  
  24.     }  
  25.   
  26.     this.subscription = this.pageService.getPage().subscribe(page => {  
  27.       if (page) {  
  28.         this.open(page);  
  29.       } else {  
  30.         // do something  
  31.       }  
  32.     });  
  33.   }  
  34.   
  35.   ngOnInit(): void {  
  36.     this.registerUserData.username   
  37.       = this.registerUserData.firstName   
  38.       = this.registerUserData.lastName   
  39.       = this.registerUserData.password   
  40.       = ""  
  41.   }  
  42.   
  43.   ValidateUser(user){  
  44.     if(!user.username || !user.firstName || !user.lastName || !user.password) return false;  
  45.     return true;  
  46.   }  
  47.   Register(user){  
  48.     if(!this.ValidateUser(user)) {  
  49.       this.dialogService.sendDialog({type:1, message: "Required Fields must be filled.."});  
  50.       return;  
  51.     }  
  52.     console.log(user);  
  53.     this._authservice.registerUser(user).subscribe(data=>  
  54.       {  
  55.         console.log("login Details:", data);  
  56.         this.dialogService.sendDialog({type: 3, message: data});  
  57.       },  
  58.       error => {  
  59.         console.log("Error: ", error);  
  60.         this.dialogService.sendDialog({type: 2, message: error});  
  61.       },  
  62.       ()=>{  
  63.         console.log("login process complete!");  
  64.       });  
  65.     console.log('Logged in!');  
  66.   }  
  67.   
  68.  open(page){  
  69.    switch(page.type)  
  70.    {  
  71.      case 1:  
  72.       this.router.navigate(['/login'], { queryParams: { }});  
  73.       break;  
  74.       default:  
  75.         console.log('some data here..');  
  76.    }  
  77.  }  

Open register.component.html and add the below selector at the end.
 
<app-prompt></app-prompt>
 
Run the application,
 
Show Hide Dialog Or Modal Service In Angular 
 
Click on Register button.
 
Show Hide Dialog Or Modal Service In Angular
 
You will get the dialog with error message. Click on close icon.
 
Let’s register a user with proper details. Click on Register button.
 
Show Hide Dialog Or Modal Service In Angular
 
On Successful registration of User you will get the prompt.
 
Let’s create a user that is already registered.
 
Show Hide Dialog Or Modal Service In Angular
 
You will get an error indicating the already taken username message.
 
How it works,
  1. Click on Register button.
  2. If fields are blank then it will sendDialog with type 1, message: “Required Fields must be filled..”.
  3. From dialog service the prompt component will receive the value of sendDialog and open the dialog accordingly.
  1. On successful creation of User it will prompt the success dialog.
  2. On clicking on Ok of dialog it will send the page with type and message through pageService.
  3. On Registering component the pageService is subscribed and on the next immediate page value it will try to open the page based on parameter passed.
  4. In simple terms, on successful creation of User it will show you a success prompt and when clicking on Ok button it will redirect to the Login Page.
  5. This is all possible because of Subject we have used in subscription and on the every new page or dialog value it will notify or emit the event to the subscribed observer and make these things possible.
Thank you.


Similar Articles