# Terminal
rails g migration add_position_to_items position:integer
rails db:migrate
# db/migrate/XXXXXX_add_position_to_items.rb
class AddPositionToItems < ActiveRecord::Migration[6.0]
def change
add_column :items, :position, :integer, default: 0
end
end
# javascript/controllers/draggable_controller.js
import { Controller } from 'stimulus'
import { Sortable } from '@shopify/draggable'
export default class extends Controller {
static targets = ['column', 'item']
initialize() {}
connect() {
if (this.hasItemTarget) {
this.itemTargets.forEach(item => {
item.setAttribute('style', 'z-index: 1000;')
})
const sortable = new Sortable(this.columnTargets, {
draggable: 'li'
})
sortable.on('sortable:stop', function(event) {
let array = Array.from(event.newContainer.children)
array.forEach((item, index) => {
if (item.classList.contains('draggable--original')) {
array.splice(index, 1)
} else if (item.classList.contains('draggable-mirror')) {
array.splice(index, 1)
}
})
let positions = array.map(item => item.dataset.id)
let url = event.dragEvent.source.getAttribute('data-url')
let column = event.newContainer.getAttribute('data-id')
let data = { item: { column_id: column }, positions: positions }
let token = document.head.querySelector('meta[name="csrf-token"]').getAttribute('content')
fetch(url, {
method: 'PUT',
credentials: 'same-origin',
headers: {
"X-CSRF-Token": token,
"Accept": "application/json",
"Content-type": "application/json"
},
body: JSON.stringify(data)
})
})
}
}
disconnect() {}
}
# views/items/_item.html.erb
<%= content_tag :li, data: { target: 'draggable.item',
id: item.id,
url: list_column_item_path(list, column, item) } do %>
# controllers/items_controller.rb
def update
params[:positions].uniq.each_with_index do |id, index|
@list.items.find(id).update(position: index + 1)
end
if @item.update(item_params)
respond_to do |format|
format.html { redirect_to @list, notice: 'Item was successfully updated.' }
format.json {}
end
else
render :edit
end
end
# controllers/lists_controller.rb
def set_list
@list = current_company.lists
.includes(columns: :items)
.order('columns.id, items.position ASC')
.find(params[:id])
end