Home > front end >  Ionic (angular) app can't assign values to property because it thinks it is readonly but it
Ionic (angular) app can't assign values to property because it thinks it is readonly but it

Time:11-12

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 ?).

  • Related