4
votes

I am using the angular material 2 dialog for adding items to a list. I have a component (AuthorListComponent) that contains the list (table). The component has a function called getAuthors that makes a rest call and renders a table in the template. I also have a button that opens a angular material 2 dialog for adding a new item:

https://github.com/angular/material2/blob/master/src/lib/dialog/README.md

What I can't figure out is when the item in the dialog is saved and the dialog closed, I want the AuthorListComponent to be refreshed so the newly added item displays. I think I have to use an event emitter somewhere to call the getAuthors function, however the dialog doesn't use a directive/html element that I can attach an event to.

This is my modal service:

import { Observable } from 'rxjs/Rx';
import { AuthorComponent } from '../author/author.component';
import { MdDialogRef, MdDialog, MdDialogConfig } from '@angular/material';
import { Injectable, ViewContainerRef } from '@angular/core';

@Injectable()
export class DialogService {

    constructor(private dialog: MdDialog) { }

    public openDialog(viewContainerRef: ViewContainerRef): Observable<boolean> {
        let dialogRef: MdDialogRef<AuthorComponent>;
        let config = new MdDialogConfig();
        config.viewContainerRef = viewContainerRef;
        config.disableClose = true;
        config.width = '600px';
        dialogRef = this.dialog.open(AuthorComponent, config);
        return dialogRef.afterClosed();
    }
}

This is the author component that gets loaded in the dialog:

import { Component, Input, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { MdDialogRef } from '@angular/material';

import { AuthorService } from './author.service';

@Component({
    moduleId: module.id,
    selector: 'author-comp',
    templateUrl: 'author.component.html'
})

export class AuthorComponent implements OnInit {
    authorId: number;
    author = {};

    constructor(
        private route: ActivatedRoute, 
        private authorService: AuthorService,
        private router: Router,
        public dialogRef: MdDialogRef<AuthorComponent>
    ) 
    { }

    ngOnInit() {
        this.authorId = this.route.snapshot.params['AuthorId'];
        if (this.authorId)
        {
            this.authorService.getAuthor(this.authorId)
                .then((author) => {
                    this.author = author;
                    })
                .catch((error) => {
                    throw ('ngOnInit-getAuthor: ' + error);
                });
        }
    }

    saveAuthor(Author: any) {
        return this.authorService.saveAuthor(Author)
            .then(() => {
                this.dialogRef.close();
            })
            .catch(error => {
                throw ('saveAuthor-component: ' + error);
            });
    }
}

This is the author list component from where the dialog is opened:

import { Component, OnInit, ViewContainerRef } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';

import { AuthorService } from './index';
import { DialogService } from '../shared/dialog.service';


@Component({
  moduleId: module.id,
  selector: 'author-list-comp',
  templateUrl: 'author-list.component.html'
})

export class AuthorListComponent implements OnInit {
  authors: any[];

  constructor(
    private authorService: AuthorService,
    private dialogService: DialogService,
    private viewContainerRef: ViewContainerRef,
    private router: Router
  )
  {}

  getAuthors() {
      this.authorService.getAuthors()
      .then((authors) => {
        this.authors = authors;        
      })
      .catch((error) => {
        throw('ngOnInit-getAuthors: ' + error)
      })
  }

  ngOnInit(){
    this.getAuthors();
  }

  public openDialog() {
    this.dialogService.openDialog(this.viewContainerRef);
  }
}

So I think I need to call the getAuthors function in the component above from either the dialog service or the author component. The other way I thought of was just to use router.navigate somehow.

Any help is appreciated!

5

5 Answers

5
votes

The simplest way to refresh parent on dialog close:

this.dialog.open(DialogComponent)
  .afterClosed()
  .subscribe(() => this.refreshParent());
4
votes

To refresh the parent, all you have to do is add this line of code right before opening your dialog :

const dialogConfig = new MatDialogConfig();
this.dialog.afterAllClosed.subscribe(data=> this.myLoadingFunction() )
this.dialog.open(myDialog , dialogConfig);

Right after closing myloadingFunction will be executed

3
votes

The afterAllClosed property helped me when I was using:

constructor(public dialog: MdDialog) {
  dialog.afterAllClosed
    .subscribe(() => {
    // update a variable or call a function when the dialog closes
      this.viewMode = 'loadingPage';
      this.getUserData();
    }
  );
 }

openDialog(){
  this.dialog.open(
    DialogComponent
  );
};
0
votes

I figured it out. I had to subscribe to the dialog service in the author list component's openDialog function.

I changed this:

  public openDialog() {
    this.dialogService.openDialog(this.viewContainerRef);
  }

to this:

  public openDialog() {
    this.dialogService
      .openDialog(this.viewContainerRef)
      .subscribe(result => {
             this.getAuthors();
      });
  }
0
votes

You can pass the form data if submit is successfull like this

saveAuthor(Author: any) {
    return this.authorService.saveAuthor(Author)
        .then(() => {
            this.dialogRef.close(this.contactForm.value);
        })
        .catch(error => {
            throw ('saveAuthor-component: ' + error);
        });
}

Then you can pass that data to the list like:

public openDialog() {
this.dialogService.openDialog(this.viewContainerRef);
dialogueref.afterClosed().subscribe((data: any) => {
  if (!data) {
    console.log('failed');
  } else {
    this.authors.unshift(data);
  }}