angular13 – Angular Can Deactivate – Material Dropdown

I have an implementation of Angular RouteGuard CanDeactivate. It works for input fields but its not working for drop downs. I also want to display my own modal and I can’t get it work correctly.

This is the HTML template code:

    <div *ngIf="!this.overallStructure" class="page-header">
   <div class="col">
      <h1>Loading please wait...</h1>
   </div>
</div>
<div *ngIf="this.overallStructure" class="content_wrapper">
<div class="container history-tabs">
   <div class="page-header">
      <div class="row">
         <div class="col-md-12">
            <h1 class="text-center mx-3 p-3">Account Structure - {{accountInfo?.name}}</h1>
         </div>
      </div>
   </div>
   <form #form="ngForm" class="form-group">
      <div class="row container-fluid px-5">
         <div class="col-md-6">
            <mat-form-field class="mx-md-5 w-100" appearance="standard">
               <mat-label>Contract Type *</mat-label>
               <mat-select [(value)]="overallStructure.contractTypeId" class="product_type required"
               (selectionChange)="OnContractTypeSelect($event)" name="contractTypeId" tabindex="1">
               <mat-option *ngFor="let item of contractType" [value]="item.id">
               {{item.name}}
               </mat-option>
               </mat-select>
            </mat-form-field>
            <mat-form-field class="mx-md-5 w-100" appearance="standard">
               <mat-label>Business Unit *</mat-label>
               <input [(ngModel)]="businessUnitName" matInput name="businessUnitName" tabindex="3">
            </mat-form-field>
            <mat-form-field class="mx-md-5 w-100" appearance="standard">
               <mat-label>Contract Period *</mat-label>
               <mat-select [(value)]="overallStructure.contractPeriod" class="product_type required" name="contractPeriod"
               tabindex="5">
               <mat-option value="Accident Year">Accident Year</mat-option>
               <mat-option value="Policy Year">Policy Year</mat-option>
               </mat-select>
            </mat-form-field>
         </div>
         <p>
            <br>
         </p>
      </div>
      <div class="row">
         <div class="col-12">
            <button title="Next" [disabled]="(disableNextButton())"
            class="btn btn-sm ptl-button text-center expandOnSmallSize mx-1  btn-right"
            (click)="navigateToLobSelection()" type="button" tabindex="16">Next</button>
            <button (click)="onClickCancel()" class="btn btn-sm ptl-button text-center expandOnSmallSize mx-1 btn-right"
               name="" tabindex="15">
            Cancel</button>
            <button [disabled]="!allMandatoryFieldsEntered()" (click)="saveOverallStructure()"
            class="btn btn-sm ptl-button text-center expandOnSmallSize mx-1 btn-right" tabindex="14">
            Save</button>
            <button title="Previous" (click)="onClickBackBtn()"
               class="btn btn-sm ptl-button text-center expandOnSmallSize mx-1 btn-right" type="button" tabindex="13">
            Previous</button>
         </div>
      </div>
   </form>
   <P><br></P>
</div>

Html component code:

import { AccountInfo } from './../general/models/accountInfo';
import { MaskService } from './../../services/mask-service.service';
import { Component, OnInit, ViewChild } from '@angular/core';
import {PricingToolService} from '../../services/pricingtoolservice.service'
import { ActivatedRoute, Router } from '@angular/router';
import { OverallStructure } from '../general/models/overallstructure';
import createNumberMask from 'text-mask-addons/dist/createNumberMask';
import { MatDialog, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { MatSnackBar } from '@angular/material/snack-bar';
import { SnackBarComponent } from '../snackBar/snackBar.component';
import { NgForm } from "@angular/forms";
import { FormCanDeactivate} from '../form-can-deactivate/form-can-deactivate';

@Component({
  selector: 'app-overall-structure',
  templateUrl: './overall-structure.component.html',
  styleUrls: ['./overall-structure.component.scss']
})
export class OverallStructureComponent extends FormCanDeactivate implements OnInit {
  @ViewChild('form')
  form: NgForm;

  constructor(public service: PricingToolService, private ActivatedRoute: ActivatedRoute,
    private router: Router){
      super();


  }


  ngOnInit(): void {

  }

  
  onClickCancel(){
    this.service.openConfirmationDialog("Cancel will remove any edit done on the Account Structure screen, Do you want to continue ?")
      .subscribe((response: any) => {
        if (response){
          this.ngOnInit();
        }
      });
  }
}

CanDeactivte Guard Service:

import { RouterStateSnapshot, ActivatedRouteSnapshot, CanDeactivate, UrlTree } from '@angular/router';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';

export interface CanComponentDeactivate {
  canDeactivate: () => Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree;
}

@Injectable()
export class CanDeactivateGuard implements 
CanDeactivate<CanComponentDeactivate> {

  canDeactivate(
    component: CanComponentDeactivate,
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot) {
     console.log("component.canDeactivate");
     return component.canDeactivate ? component.canDeactivate() : 
true;
  }
}

Abstract FormComponent

import { Observable, of } from 'rxjs';
import { NgForm } from "@angular/forms";
import { MessageDialog } from '../message-dialog/messageDialog.component';
import { PricingToolService } from '../../services/pricingtoolservice.service';
import { HostListener } from "@angular/core";
import { Injectable } from '@angular/core';

@Injectable()
export abstract class FormCanDeactivate {
 abstract get form() : NgForm;

 canDeactivate() : boolean {
    if(this.form.dirty){
      if (confirm("You have unsaved changes! If you leave, your changes will be lost.")) {
          return true;
      } else {
        return false;
      }
    }
    return true;
  }

  @HostListener('window:beforeunload', ['$event'])
  unloadNotification($event: any) {
      if (!this.canDeactivate()) {
          $event.returnValue = true;
      } else {
        console.log("In can deactivate abstract");
      }
  }

    }

I’m not sure what I’m missing but I just need canDeactivate to work when the drop downs change. I am using Angular 13.

Leave a Comment