I have a form to create and account: email, name, password ... and I want the app to display a message to the user when the creation is successful , more precisely when effect create the action that tells the user is created.
My question is: What is the best way to tell the component that the user is correctly created?
For the moment I have done this:
When the UserCreated action is called after service is done, I update the store with the id of the newly created user.
I subscribe to a selector in ngOnInit that sends the value of the id: if it's not empty I display a message.
I have the feeling that is not the best way to do this: I would like to avoid setting an id (or a boolean true/false) to the store that uses a selector.
I would like the component to subscribe to the action: UserCreated instead, I feel that is cleaner (I might think wrong too).
I have seen some posts on action subscribing but it's not working for me (the posts were related to older version of angular and methods didn't exists anymore).
Submitting form: createaccount.component.ts
this.store.dispatch(new UserServerCreation({ user: _user }));
createaccount.action.ts
export class UserServerCreation implements Action {
readonly type = UserActionTypes.UserServerCreation;
constructor(public payload: { user: User }) { }
createaccount.effects.ts
@Effect()
createUser$ = this.actions$
.pipe(
ofType<UserServerCreation>(UserActionTypes.UserServerCreation),
mergeMap(({ payload }) => {
return this.userService.createUser(payload.user).pipe(
tap(res => {
this.store.dispatch(new UserCreated({ user: res.payload }));
}),
catchError(error => {
this.snackBar.open(this.translateService.instant(error.error.errors.message), 'Error', {
duration: 5000,
});
return of([]);
}),
);
}),
);
createaccount.selector.ts
export const selectLastCreatedUserId = createSelector(
selectUsersState,
usersState => usersState.lastCreatedUserId
);
Selector subscription in createaccount.component.ts
ngOnInit() {
this.store.pipe(select(selectLastCreatedUserId)).subscribe(newId => {
console.log('ID: ' + newId);
if (newId) {
const message = this.translateService.instant('USER.CREATED');
this.layoutUtilsService.showActionNotification(message, MessageType.Create, 5000, true, false);
this.userForm.reset();
}
});
}
UPDATE SOLUTION:
Finally achieved to subscribe to action channel (this was my preferred method over snackbar in the effect)
On my createaccount.component.ts I add those samples: variable:
destroy$ = new Subject<boolean>();
in the constructor:
private actionsListener$: ActionsSubject
then in ngOnInit:
this.actionsListener$
.pipe(ofType(UserActionTypes.LoginOnDemandCreated))
.pipe(takeUntil(this.destroy$))
.subscribe((data: any) => {
// Do your stuff here
console.log('DATA : ' + JSON.stringify(data)); //Just for testing purpose
});
Finally in ngOnDestroy:
ngOnDestroy() {
this.destroy$.next(true);
this.destroy$.complete();
}
Thanks for help !
I know two way:
{ dispatch: false }
which means the effect doesn't dispatch any action but can do some logic, like open a Snackbar. (ofType<UserServerCreated (UserActionTypes.UserServerCreated)
) and add simply a tap
operator function, and do the same as in the catchError
.