How do I pass data from MatDialog => Rxjs Effect => Component?

763 views Asked by At

My component is calling an Action and using @Effect to open the Dialog. The Dialog send the data back to the @Effect. I'm able to see the data using .afterClosed() in the @Effects, but I don't know how to get it to the component using .afterClosed().

Here is how the component is calling the dialog:

this.store.dispatch(new fromWorkspace.ShowDialog());

Here is the Dialog in the Effects:

  @Effect({ dispatch: false })
   showDialog$ = this.actions$.pipe(
    ofType(WorkspaceActionTypes.ShowDialog),
    map(action => {
      this.dialogRef = this.addPersonDialog.open(PersonSelectorComponent, {
        disableClose: false,
        hasBackdrop: true,
        restoreFocus: true,
        data: { }
      });
      // I can see the data here;
      this.dialogRef.afterClosed().subscribe(result => console.log(result));
    })
  );

Here is how the Dialog is sending data back:

constructor(@Inject(MAT_DIALOG_DATA) public data: any,
              public dialogRef: MatDialogRef<PersonSelectorComponent>) { }


 addPerson(event: MatAutocompleteSelectedEvent) {
    if (event.option.selected) {
      const person = event.option.value;
      if (person) {
      this.dialogRef.close(person);
      // data is correct here;
      console.log(person);
      }
    }

Back to the component here is how I'm trying to use .afterClose():

public dialogRef: MatDialogRef<PersonSelectorComponent>


//this does not work
this.assigneeDialogRef.afterClosed().subscribe(result => console.log(result));

2

There are 2 answers

0
CZar On BEST ANSWER

So, going forward with action/reducer approach I did as follow:

  • created a new action "addPerson/addPersonSuccess" (to avoid subscribing to the data returned from the Dialog.
  addPerson$ = this.actions$.pipe(
    ofType(WorkspaceActionTypes.AddPerson),
    map(action => {
      return new AddPersonSuccess(action.payload);
    }),
    catchError(error => this.dispatchErrorHandleActions(new addPersonFailure(error),
            `Couldn't add person. Please try again later.`))
  );
  • then dealt with it in the reducer:
 case WorkspaceActionTypes.AddPersonSuccess:

      return update(state, {
        person: {
          data: { $set: action.payload }
        }
      });
  • and included a Selector in the reducer as well:
export const addPerson = createSelector(getWorkspaceState, (state: WorkspaceState) => state.person);
  • then back in the component call it in the constructor:
 this.person$ = this.store.select(fromWorkspace.addPerson);
  • now I can get the data by subscribing to the 'this.person$' observable.
3
Kyle Anderson On

Generally from an effect you would dispatch an action with the resulting data which would go through your reducer and then end up in your data store. From there your component would be subscribed to the data store (via a selector) and would get the updated data that way.

If you're using an effect to directly get the data and return it to your component without putting it in the store then I wouldn't use an effect at all. I'd just call the dialog directly and get the result and do what I want with it.