Reputation: 9380
I am trying to develop a a simple angular app using NgRx
to maintain state.
Unfortunately, the callback to the subscription to the store gets fired but always returns an empty object.
I am trying to dispatch the object to store as
this._store.dispatch({
type: 'ShowPassword',
payload: value
})
and a look at the reducer function
export function showPasswordReducer(state, action) {
//console.log(state);
switch (action.type) {
case 'ShowPassword':
return {
...state,
'ShowPassword': action.payload
}
break;
default:
return state;
}
}
I am adding the reference of StoreModule
in the imports array of root module as
StoreModule.forRoot(showPasswordReducer)
and subscribing to the store as
this._store.subscribe(val => {
if (val)
this.showPassword = val.ShowPassword;
})
Stackblitz link: https://stackblitz.com/edit/angular-first-ngrx-demo
Upvotes: 1
Views: 2456
Reputation: 73357
You are using ngrx 8, so you should embrace that syntax, which is also cleaner in my opinion. We now have access to createReducer
and createAction
. So I suggest the following:
import { createAction, createReducer, on, } from '@ngrx/store';
export const showPwd = createAction(
'Show Password',
({ showPw }: { showPw: boolean }) => ({
showPw,
})
)
const initialState = {
showPw: false
};
export const showPasswordReducer = createReducer(
initialState.showPw,
// here you would probably want to have the action(s) in a separate file
on(this.showPwd, (state: any, action: any) => {
return action.showPw;
}),
)
export function reducer(state: any | undefined, action: any) {
return showPasswordReducer(state, action);
}
Then remember to mark to app.module imports
:
StoreModule.forRoot({showPwd: showPasswordReducer})
Then finally in the component where you dispatch the action and listen to store:
ngOnInit() {
this._store.subscribe(val => {
if (val && val.showPwd)
this.showPassword = val.showPwd;
})
}
ToggleCheckbox(value: boolean) {
this._store.dispatch(showPwd({showPw: value}))
}
Your forked STACKBLITZ
Upvotes: 2
Reputation: 5602
There are a couple of basic NGRX pieces missing in your code -
Let's deal with them one by one:
a) You must have an initial state [I am assuming that you want to have a state which tracks a boolean called showPassword
]. Define an initial state object like this:
export const initialState = {
showPassword: false
};
b) Setup your reducer to make use of initial state like this:
export function showPasswordReducer(state = initialState, action) {
//console.log(state);
switch (action.type) {
case 'ShowPassword':
return {showPassword: action.payload};
break;
default:
return state;
}
}
Notice that in case of default action reducer will return the initial state.
c) Now inject the reducer in forRoot
method with the state name like this:
@NgModule({
imports: [BrowserModule, FormsModule, StoreModule.forRoot({ShowPassword: showPasswordReducer})],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
d) Now subscribe to the store [Ideally You MUST have selectors to get the piece of information from the store but to keep things simple, simply subscribe to the store directly and look for the same property which was used in the forRoot
like this:
ngOnInit() {
this._store.subscribe(val => {
console.log(val);
if (val)
this.showPassword = val.ShowPassword.showPassword;
})
}
Working stackblitz - https://stackblitz.com/edit/angular-first-ngrx-demo-7yrl2r?file=src/app/app.module.ts
Hope it helps.
Upvotes: 2