Reputation: 2324
I need to close angular material dialog from @ngrx/effect
here is my code
import { MatDialogRef, MatDialog } from "@angular/material/dialog";
import { AddComponent } from "./../../add/add.component";
@Injectable()
export class UserEffects {
@Effect()
addNewUser$ = this.actions$.pipe(
ofType(actions.UserActionTypes.addNewUser),
mergeMap((user: actions.addNewUser) =>
this.userService.createUser(user.user).pipe(
map(() => {
new actions.LoadUsers(),
this.notificationService.success("User added successfully!");
this.dialogRef.close(); <------ // here i try to close
}),
catchError(error => of(new actions.Error(error.error)))
)
)
);
constructor(
private actions$: Actions<actions.UserActions>,
private userService: UserService,
private notificationService: NotificationPopUpServiceService,
public dialogRef: MatDialogRef<AddComponent>
) {}
}
And with this i get error
main.ts:13 NullInjectorError: R3InjectorError[EffectsRootModule -> InjectionToken ngrx/effects: Root Effects -> UserEffects -> MatDialogRef -> MatDialogRef -> MatDialogRef]: NullInjectorError: No provider for MatDialogRef!
What is the best way to close material-dialog from effect or from service? Because we always need to set a name for the dialog component?
Thank you
Upvotes: 8
Views: 4144
Reputation: 2324
I think I find a solution, but If there something better pls, let me know...
I add this.dialogRef.closeAll()
class UserEffects {
constructor(
private actions$: Actions,
private dialogRef: MatDialog,
private notificationService: NotificationService,
) {}
@Effect()
addNewUser$ = this.actions$.pipe(
ofType(actions.UserActionTypes.addNewUser),
mergeMap((user: actions.addNewUser) =>
this.userService.createUser(user.user).pipe(
map(() => {
new actions.LoadUsers(),
this.notificationService.success("User added successfully!");
this.dialogRef.closeAll(); <--- //this is the key
}),
catchError(error => of(new actions.Error(error.error)))
)
));
}
EDIT:
modal is closed, but I get error
core.js:6014 ERROR Error: Effect "UserEffects.addNewUser$" dispatched an invalid action: undefined
TypeError: Actions must be objects
Any help? Thnx
Upvotes: 2
Reputation: 69
I think the best solution to closing dialog is subscribing to the effect variable ie
// close the dialog
// Inside the dialog component
this.userEffects.addNewUser$.pipe(
ofType(Actions.LoadUsers)
).subscribe(_ => this.matDialogRef.close());
Upvotes: 4
Reputation: 21
You could listen to actions$: Actions
in your dialog component, subscribe to it and close the dialog when the action is triggered, without recurring to NgRx effects and needing to inject all the dialogs references.
Your dialog component's constructor would include, among other things:
constructor(
public dialogRef: MatDialogRef<YourDialogComponent>,
private readonly actions$: Actions) {}
In ngOnInit
you'd listen to the relevant action meant to close the dialog. I generally rely on ngOnDestroy
to unsubscribe from observables.
private readonly subscription = new Subscription();
ngOnInit(): void {
this.subscription.add(
this.actions$
.pipe(ofType(actions.UserActionTypes.LoadUsers))
.subscribe(() => this.dialogRef.close())
);
}
ngOnDestroy(): void {
this.subscription.unsubscribe();
}
Pay attention to the action you're listening to; it must be one triggered by the addNewUser$
effect, which seems to be new actions.LoadUsers()
in your case. The common pattern is to follow an addNewUser
action with an addNewUserSuccess
or addNewUserFailure
.
You may have several error dialogs popping up at the same time. This approach allows one to manage concurrent dialogs made of different components: closeAll()
will (unsurprisingly) close all the material dialogs.
Upvotes: 2
Reputation: 46
regarding your 'dispatched an invalid action: undefined'
every effect must dispatch an action, unless you specify: { dispatch: false }
Upvotes: 1
Reputation: 6821
In the constructor of your @Effect
, you need to provide the dependency:
private dialogRef: MatDialogRef<MyDialogComponentToClose>
And you need to import MatDialogModule
inside your module where your effect is.
Upvotes: 0