How can I make bigger changes to ngxs state structure

19 Views Asked by At

in my hobby project I wanted to create a annual goal planer with Angular. Each goal can be assigned to a quarter of the year. The object AnnualGoals consists of 5 lists with goal objects - q1, q2, q3, q4 and not assigned. All of this is in my nice ngxs state. All good.

Now I want to move one goal into another quarter and this seems unreasonably difficult. I managed to get a working code but it feels like I'm violating the basic concepts of ngxs by mutating all of the arrays. My result is the following:

 @Action(MoveGoal)
  moveGoal(ctx: StateContext<any>, moveAction: MoveGoal) {

    // make a bff call
     [...]

    // update state
    const state = ctx.getState();

    // remove the goal from the list (we don't know where it was)
    const q1Update: Array<Goal> = [...state.annualGoal.q1].filter((goal: Goal) => goal.id !== moveAction.goal.id)
    const q2Update: Array<Goal> = [...state.annualGoal.q2].filter((goal: Goal) => goal.id !== moveAction.goal.id)
    const q3Update: Array<Goal> = [...state.annualGoal.q3].filter((goal: Goal) => goal.id !== moveAction.goal.id)
    const q4Update: Array<Goal> = [...state.annualGoal.q4].filter((goal: Goal) => goal.id !== moveAction.goal.id)
    const notAssignedUpdate: Array<Goal> = [...state.annualGoal.notAssigned].filter((goal: Goal) => goal.id !== moveAction.goal.id)

    // now add it where it is supposed to be
    if (moveAction.moveTo === Columns.NONE) {
      notAssignedUpdate.splice(0, 0, moveAction.goal);
    }
    if (moveAction.moveTo === Columns.Q1) {
      q1Update.splice(moveAction.index, 0, moveAction.goal);
    }
    if (moveAction.moveTo === Columns.Q2) {
      q2Update.splice(moveAction.index, 0, moveAction.goal);
    }
    if (moveAction.moveTo === Columns.Q3) {
      q3Update.splice(moveAction.index, 0, moveAction.goal);
    }
    if (moveAction.moveTo === Columns.Q4) {
      q4Update.splice(moveAction.index, 0, moveAction.goal);
    }

    // and since it's not clear, I need to update all of the lists of the state
    ctx.setState({
      ...state,
      annualGoal: {
        ...state.annualGoal,
        q1: q1Update,
        q2: q2Update,
        q3: q3Update,
        q4: q4Update,
        notAssigned: notAssignedUpdate
      }
    });
  }

So my question is: is this solution okay? Are there better ways to achieve it? Or is my data model just badly designed (generally or only for ngxs?)

Thanks for taking the time to think about it!

I tried to use the ngxs operator updateItem, but never got it to work with multiple arrays updated at once. I also thought about changing the data model into a flat lists of goals than have an enum attribute quarter. That would probably make the state nicer but felt less intuitive to work with it.

0

There are 0 best solutions below