I'm learning Angular 2 and i'm trying to user ngrx/store, but i have some difficulties with some special cases.
Example I'm trying to remove a parent object. What i want to do, is to remove also child objects.
Here are my entities :
export class Discussion {
id: string;
name: string;
createdAt: Date;
posts: Post[];
}
export class Post {
id: string;
title: string;
data: string;
createdAt: Date;
comments: Comment[];
}
export class Comment {
id: string;
data: string;
createdAt: Date;
}
I'm using normalizr to flatten my state so my stored discussion will look like:
{
id: "1",
name: "First dicussion",
createdAt: "...",
posts: ["1", "2", "3", "5"]
}
I have 3 reducers, One reducer for Discussions, another one for Posts and the last for Comments. All reducers handles delete Action of it own type. Here is an example of Discussion reducer:
export function reducer(state = initialState, action: discussion.Actions): State {
switch (action.type) {
case discussion.REMOVE: {
const idToRemove = action.payload;
const newEntities = state.entities;
delete newEntities[idToRemove];
return Object.assign({}, state, {
entities: newEntities
});
}
}}
My action look like this :
export class RemoveAction implements Action {
readonly type = REMOVE;
/**
* Constructor
* @param payload The id of the discussion to remove
*/
constructor(public payload: string) { }
}
When I delete a discussion, I want to delete posts related to the discussion and posts effect will delete comments related to the deleted posts. I used effects of ngrx do do that so I used this effect :
@Effect()
removeDiscussion: Observable<Action> = this._actions
.ofType(dicussion.REMOVE)
.map((action: discussion.RemoveAction) => action.payload)
.mergeMap(discId => {
// How to get posts from discussion id ???
// Fire related Actions
return [
new posts.RemoveAction(postsToRemove)
];
});
My question is how to get posts to remove from an Id of discussion ?
Thanks for reading.
You can access the store in an effect by using withLatestFrom
.
(import 'rxjs/add/operator/withLatestFrom';
)
Inject the store in the effects-class:
constructor(private _actions: Actions, private store: Store<fromRoot.State>)
Use it in the effect:
@Effect()
removeDiscussion: Observable<Action> = this._actions
.ofType(dicussion.REMOVE)
.map((action: discussion.RemoveAction) => action.payload)
.withLatestFrom(this.store, (payload, state) => ({ discId: payload, state }))
.mergeMap(({ discId, state }) => {
// access the posts array of the discussion
const postsToRemove = state.discussions[discId].posts;
// Fire related Actions
return [
new posts.RemoveAction(postsToRemove)
];
});
The syntax .mergeMap(({ discId, state }) => ...
is called destructuring.
If you don't like this syntax, it can be replaced with .mergeMap((payloadAndState) => ...
. Then you would access discId
by doing payloadAndState.discId
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With