How to update order of entities in NGRX? angular 9

2.3k Views Asked by At

I am building an application, where I have N columns (N lists of items) and by using a drag & drop from angular material I am able to move items between them. I am also using NGRX and EntityAdapter in my app.

I would like to ask, how can I properly update the order of items when I am moving a object?

Example: Moving first item from the "To do" column. that item should be put between brush teeth and pick up groceries.

enter image description here

Right now I know how to update column of every item of my list. The thing that I do not know is how to put it in the correct order (sorting is by default, so probably by id).

Item interface:

export interface Item {
  id:string;
  title:string;
  columnId:string;
}

Dispatching action for columnId update :

drop(event: CdkDragDrop<string[]>) {
  const droppedItem: SavedJob = event.item.data;
  const previousColumn = event.previousContainer.id;
  const currentColumn = event.container.id;
  this.store.dispatch(
    updateColumn({
      updates: {
        id: droppedItem.id,
        changes: {
          columnId: currentColumn
        }
      }
    })
);

Reducer:

on(SavedJobsActions.updateColumn,(state,action)=> {
  return savedJobsAdapter.updateOne(action.updates, {
    ...state,
    entities: {
      ...state.entities,
      [action.updates.id]: {
        ...state.entities[action.updates.id]
      }
    }
  })
})

How should I properly update both columnId and the order of each item ? I know I should add order key for each Item, but then updating the order value for each column might be hard.

2

There are 2 best solutions below

0
On

See https://ngrx.io/guide/entity/adapter: sortComparer: A compare function used to sort the collection. The comparer function is only needed if the collection needs to be sorted before being displayed. Set to false to leave the collection unsorted, which is more performant during CRUD operations.

So if you insert a new value, your whole Dictionary should be sorted if you provider a sortComparer. Otherwise it defaults to ID I believe. Implementation of the Comparer depends on how you want to sort, but it should somewhat look like this (assuming columnId is never null).

createEntityAdapter({
   sortComparer: (item1: Item, item2: Item) => item1.columnId.localeCompare(item2.columnId),
})
0
On

I have the same situation. My workaround is that I put a new attribute called index.

For example

interface Listing {
 name: string;
 index: number;
}

Then, each time the UI sorting happened, let's change the index as well. In the other words, the selector result will be changed by position. Then you can get the sorting result.

you still need to use "sortComparer" to get the sorting result, but don't use id for sorting, because what we updated is not the ID, it's index.

You can check this index sorting technique as well.