htmlangulartypescriptmddialogangular2-toaster

Md-dialog close after notification


I have dialog box where user can enter data and after clicking on "create", my dialog box gets close and user gets notification. I want to close my dialog box after user get notification and if user enters wrong data, user should get notification for that too and dialog box should not get close.

Currently, everything is working properly but I want my dialog box should disappear after notification (toster service).

Can anyone help me with this thing so that my dialog box will stay till i get notification for success and also for error?

exhibit.component.ts (main component)

  createExhibit(event: any) {
    let context = this;
    this.createDialogRef = this.dialog.open(CreateExhibitDialogComponent, { width: '45em', data: {} });
    this.createDialogRef.afterClosed().subscribe(
      (newExhibit: Exhibit) => {
        if (newExhibit.latitude) { newExhibit.latitude = newExhibit.latitude.toString().replace(/,/g, '.'); }
        if (newExhibit.longitude) { newExhibit.longitude = newExhibit.longitude.toString().replace(/,/g, '.'); }
        if (newExhibit) {
          this.exhibitService.createExhibit(newExhibit)
            .then(
              () => {
                this.toasterService.pop('success', this.translate('exhibit saved'));
                setTimeout(function () {
                  context.reloadList();
                }, 1000);
              }
            ).catch(
              error => this.toasterService.pop('error', this.translate('Error while saving'), error)
            );
        }
        this.createDialogRef = null;
      }
    );
  }

createExhibit.component.ts

<h1 md-dialog-title>{{ 'create exhibit' | translate }}</h1>

<md-dialog-content>
  <form id="new-exhibit-form">
    <md-input-container>
      <input mdInput placeholder="{{ 'name' | translate }}" [(ngModel)]="exhibit.name" name="name" required>
    </md-input-container>
    <md-input-container>
       <textarea
         mdInput
         mdTextareaAutosize
         #autosize="mdTextareaAutosize"
         placeholder="{{ 'description' | translate }}"
         [(ngModel)]="exhibit.description"
         name="desc"></textarea>
    </md-input-container>

    <div layout="row" layout-align="start center" flex>
      <md-icon _ngcontent-c7="" class="mat-icon material-icons centered" role="img" aria-hidden="true">search</md-icon>
      <md-input-container>
        <input mdInput  placeholder="search for location" autocorrect="off" autocapitalize="off" spellcheck="off" type="text" class="form-control" #search [formControl]="searchControl">
      </md-input-container>
      <md-input-container>
        <input (blur)="updateMap()" mdInput type="number" min="-90" max="90" step="0.000001"
               placeholder="{{ 'latitude' | translate }}" [(ngModel)]="exhibit.latitude" name="lat">
      </md-input-container>
      <md-input-container>
        <input (blur)="updateMap()" mdInput type="number" min="-180" max="180" step="0.000001"
               placeholder="{{ 'longitude' | translate }}" [(ngModel)]="exhibit.longitude" name="long">
      </md-input-container>
      <md-select  class="align-right" placeholder="{{ 'status' | translate }}" [(ngModel)]="exhibit.status" name="status">
        <md-option *ngFor="let statusOption of statusOptions" [value]="statusOption">{{ statusOption | translate }}</md-option>
      </md-select>
    </div>
    <agm-map (mapClick)="selectLocation($event)" [zoom]=15 [latitude]="lat" [longitude]="lng">
      <agm-marker [iconUrl]="'../../../images/map-marker.png'" *ngIf="exhibit.longitude && exhibit.latitude" [latitude]="exhibit.latitude" [longitude]="exhibit.longitude"></agm-marker>
    </agm-map>
  </form>
</md-dialog-content>

<md-dialog-actions align="end">
  <button md-dialog-close md-raised-button>
    {{ 'cancel' | translate }}
    <md-icon>cancel</md-icon>
  </button>
  <button md-raised-button [disabled]="!exhibit.isValid()" color="primary" (click)="dialogRef.close(exhibit)">
    {{ 'create' | translate }}
    <md-icon>add_circle</md-icon>
  </button>
</md-dialog-actions>

how to do this?


Solution

  • As windmaomao stated you need to manulally call dialog close() method. Material Dialog component proivide Observable only from afterClose() or beforeClose() and these methods listen to data passed through close() method. The close() method closes the dialog ofcourse what is not our expectation. You need to implement your own communication system between component and dialog build with kind of Observable or EventEmitter. I have prepared simplified solution of your problem. The trick is you can obtain reference to any field or method of your dialog component with 'componentInstance' getter.

    Dialog component

      import {Component, EventEmitter, OnInit} from '@angular/core';
      import {MatDialogRef} from "@angular/material";
    
      @Component({
        selector: 'app-simple-dialog',
        template: `<h2 mat-dialog-title>Entering some data</h2>
        <mat-dialog-content>Is data OK?</mat-dialog-content>
        <mat-dialog-actions>
          <button mat-button (click)="actionNo()">No</button>
          <button mat-button (click)="actionYes()">Yes</button>
        </mat-dialog-actions>`,
        styleUrls: ['./simple-dialog.component.css']
      })
      export class SimpleDialogComponent implements OnInit {
    
        private _action: EventEmitter<boolean> = new EventEmitter<boolean>();
        answer = this._action.asObservable();
    
        constructor(public dialogRef: MatDialogRef<SimpleDialogComponent>) { }
    
        actionYes() {
          this._action.next(true);
        }
    
        actionNo() {
          this._action.next(false);
        }
    
        closeDialog() {
          this.dialogRef.close();
        }
    
        ngOnInit() {
        }
    
      }
    

    And HTML template excerpt code to include in your main component:

        <button (click)="openDialog()">Open Dialog</button>
    

    The code of openDialog() method:

    openDialog() {
      let dialogRef = this.dialog.open(SimpleDialogComponent);
      dialogRef.componentInstance.answer.subscribe( answer => {
        console.log('Answer from Dialog: ' + answer);
        switch(answer) {
          case true:
            console.log('Data is OK. Closing dialog');
            //do some complicated stuff
            dialogRef.componentInstance.closeDialog();
            //can be simple: dialogRef.close(); 
            break;
          case false:
            console.log('Data is not OK. Not closing dialog. Show some toaster');
            break;
        }
        }
      )
    }