I'm creating some app using Ionic with Angular and I'm facing some strange issue with assigning properties.
So, I have simple component which is rendering some filters for user to choose:
<ng-container *ngFor="let filter of filters; let idx = index">
<div >
{{ filter.text | transloco | uppercase }}
<div (click)="handleFilterClick(idx, $event)">
<app-icon-button
[color]="filter.isActive ? activeIconColor : inActiveIconColor"
[src]="filter.iconSrc"
>
</app-icon-button>
</div>
</div>
</ng-container>
Filters array looks like this:
filters: Filter[];
constructor(
private store: Store<AppState>,
) {}
ngOnInit() {
this.filters = [
{
iconSrc: 'assets/icons/white-filters-icons/parking.svg',
text: 'shared.attribute.parking',
isActive: false,
filter: Attribute.PARKING,
},
{
iconSrc: 'assets/icons/white-filters-icons/wc.svg',
text: 'shared.attribute.wc',
isActive: false,
filter: Attribute.WC,
},
{
iconSrc: 'assets/icons/white-filters-icons/food.svg',
text: 'shared.attribute.food',
isActive: false,
filter: Attribute.FOOD,
}
]
}
Filters are rendered correctly without any issues, but then I have a function which handles filters clicking and it looks like this:
handleFilterClick = (idx: number, e: MouseEvent): void => {
this.filters[idx].isActive = !this.filters[idx].isActive;
const selectedFilters = [...this.filters.filter(el => el.isActive)];
this.store.dispatch(new SetSelectedFilters({ filters: selectedFilters }));
e.stopImmediatePropagation();
};
When I click first time on any of filters it works correctly, filter color is being changed, dispatch action is being executed, but then if I click at any previously clicked filter it just stops working and I can see an error in console which says: "Attempted to assign to readonly property.". It works fine only if I delete line with store dispatch function
this.store.dispatch(new SetSelectedFilters({ filters: selectedFilters }));
Can anybody tell me how it is possible?
EDIT:
SetSelectedFilters and reducer are created like this:
export enum ActionTypes {
SET_SELECTED_FILTERS = '[Map] Set selected filters',
}
export class SetSelectedFilters implements Action {
readonly type = ActionTypes.SET_SELECTED_FILTERS;
constructor(public payload: { selectedFilters: Filter[] }) { }
}
export type Actions = SetSelectedFilters;
Reducer here:
export interface MapState {
selectedFilters: Filter[];
};
export const initialState: MapState = {
selectedFilters: [],
};
export const reducer = (
state = initialState,
action: fromMap.Actions
): MapState => {
switch (action.type) {
case fromMap.ActionTypes.SET_SELECTED_FILTERS: {
return {
...state,
selectedFilters: action.payload.selectedFilters,
};
}
default: {
return state;
}
}
};
CodePudding user response:
You have this error since in the Ngrx runtime checks the strictActionImmutability
is set to true (it will be automatically disabled in production builds).
https://ngrx.io/guide/store/configuration/runtime-checks
So, you can set this flag to false or you need to ensure the immutability of the action object (maybe by making a deep clone of the filters ?).