I've been trying to wrap my head around getting SortableJS to work with multiple lists with todos and serializing the ids. Similar to how jQuery Sortable serialize method works.
Todos in each list will always begin at 1 and increment as todos are added and decrement as todos are removed.
For example:
Todo List One has three todos
- Todo 5, position: 1
- Todo 1, position: 2
- Todo 9, position: 3
Todo List Two has five todos
- Todo 5, position: 1
- Todo 1, position: 2
- Todo 9, position: 3
- Todo 17, position: 4
- Todo 2, position: 5
I've gotten sortableJS working with stimulusJS. Once any additional lists are added, the todos continue to be treated like they all belong to one list, so if there are 8 todos (three todos in List One and 5 todos in List Two), the respective positions will be 1-8 and not 1-3 and 1-5.
Here is my current configuration:
drag_controller.js
import {Controller} from "stimulus"
import Sortable from "sortablejs"
export default class extends Controller {
connect() {
this.sortable = Sortable.create(this.element, {
animation: 150,
// handle: '.fa-grip-vertical',
onEnd: this.end.bind(this)
})
}
end(event) {
let id = event.item.dataset.id
let data = new FormData()
data.append('position', event.newIndex + 1)
Rails.ajax({
url: this.data.get("url").replace(":id", id),
type: 'PATCH',
data: data
})
}
}
todos_controller.rb
def sort
authorize(:todo, :sort?)
@todo.insert_at(params[:position].to_i)
head(:ok)
end
_todo_list.html.erb
<div data-controller="drag" class="list-group list-group-flush" data-drag-url="/todos/:id/sort">
<% todo_list.todos.order(complete: :asc, position: :asc).each do |todo| %>
<%= content_tag :div, class: 'list-group-item list-group-item-action', "data-id": todo.id do %>
<!-- iterated todos -->
...
<% end %>
<% end %>
</div>
A custom sort route would be needed as a collection that takes serialized data.
The sort action will do something like this:
def sort
params[:todo].each_with_index do |id, index|
Todo.where(id: id).update_all(position: index + 1)
end
head(:ok)
end
I'm aware of using the toArray() method, i.e. this.sortable.toArray(), which will give me an array of the ids in the list. I'm not sure how to make that work in my drag_controller.js and SortableJS. How do I get serialized data from the drag_controller.js to my sort action?