I need to enter 2 input values that shows the Usage of a storage space in megabytes (used_space and remaining_space) via a form and show the entered values from ngrx/Store. Each time the form is submitted the new values are showed and the old ones are updated. The problem is that the UI shows always the default values of (used_space and remaining_space) and I do not know if my architecture is right since I am new in ngrx/store.
Model (usage.model.ts):
export interface Usage {
used_space: number;
remaining_space: number;
}
Actions (usage.actions.ts):
export const EDIT_USAGE = '[Usage] Edit';
...
export class EditUsage implements Action {
readonly type = EDIT_USAGE
constructor(public payload: Usage) {}
}
...
export type All = Reset | EditUsage;
Reducer (usage.reducer.ts): export type Action = UsageActions.All;
/// Default app state
const defaultState: Usage = {
used_space: 2,
remaining_space: 3
}
/// Helper function to create new state object
const newState = (state, newData) => {
return Object.assign({}, state, newData)
}
export function usageReducer(state: Usage = defaultState, action: Action) {
switch(action.type) {
case UsageActions.EDIT_USAGE:
// return [...state, action.payload];
return newState(state, { Usage: action.payload });
case UsageActions.RESET:
return defaultState;
default:
return state;
}
}
In app.component.ts:
usage: Observable<Usage>
constructor(private store: Store<AppState>) {
this.usage = this.store.select('usage')
}
editUsage(used_space,remaining_space) {
this.store.dispatch(new UsageActions.EditUsage({used_space:used_space , remaining_space:remaining_space}) )
}
In app.component.html:
<input type="text" #used_space>
<input type="text" #remaining_space>
<button (click)="editUsage(used_space.value,remaining_space.value)" >Edit Space</button>
<div *ngIf="usage | async as u">
<h2>Used space: {{ u.used_space }}</h2>
<h2>remaining space: {{ u.remaining_space }}</h2>
</div>
I am not seeing any result and I do not know what is wrong.
The problem lies in your reducer
:
switch(action.type) {
case UsageActions.EDIT_USAGE:
return newState(state, { Usage: action.payload }); <<--------
}
you are passing previous state and a new object with usage as a property
. What Object.assign
does is: create a new object, append previous state to it, attach a brand new property Usage
and add new values of store to that. Here's view of newly created object:
You can solve this passing the payload
directly:
switch(action.type) {
case UsageActions.EDIT_USAGE:
return newState(state, action.payload);
}
Working Demo
Plus, as long as you are updating object as whole in your reducer, I believe you don't need Object.assign()
too. You can directly return the action.payload
as it is the new state.
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