Mathias
Mathias6mo ago

How to implement sort by reordering items in a list?

I'm about to implement sorting in a table, where I would like to use either Framer motion or Atlassian Pragmatic drag and drop. Has anyone experience with mutations and how this can be done? This is the schema for what I want to sort by the ordercolumn.
js
statuses: defineTable({
name: v.string(),
description: v.optional(v.string()),
color: v.string(),
order: v.number(),
projectId: v.string(),
templateId: v.optional(v.string()),
})
.index("by_project", ["projectId"])
.index("by_template", ["templateId"]),
js
statuses: defineTable({
name: v.string(),
description: v.optional(v.string()),
color: v.string(),
order: v.number(),
projectId: v.string(),
templateId: v.optional(v.string()),
})
.index("by_project", ["projectId"])
.index("by_template", ["templateId"]),
Framer motion reorder seems to do it by index and using states. I would like to avoid states if possible and do mutations directly. What do you think is a good way to do this?
Reorder | Framer for Developers
Create drag-to-reorder effects with a simple set of components.
2 Replies
erquhart
erquhart6mo ago
In terms of state management, mutations with optimistic updates should work well. If the max expected list size is small and you're okay potentially updating every list item to represent a single drop, then that's all you need.
ian
ian6mo ago
I'd add "order" to each index, so it's sorted by order when you do .withIndex("projectId", q => q.eq("projectId", projectId)) There's some other threads with more complex ordering algorithms, and I've thought over a few myself. One one that I think is the easiest is: 1. Assign order to be Date.now() when you insert (so you don't have to query for what the next number should be - is more scalable on inserts) 2. To re-order, re-assign the orders. So if you swap two adjacent items, they get each others "order" (creation times). If you ever find two with exactly the same creation time when trying to reorder (very rare I'd imagine) you could increment one by a nanosecond (or some unit smaller than is stored by creation time by default). The slow case is moving an item from the end to the beginning, since each item then gets its order from the item that came after it. So you shouldn't move an item more than a ~1000 positions at a time like this. Drag & drop is a good fit though - since that would be a long drag. To move something to the beginning, you could just set it to be a second before the first item. And moving to the end is just changing the order to a second after the last.

Did you find this page helpful?