x
1
2
3
4
5
6
7
8
<div class="card flex flex-col gap" style="max-inline-size: 400px" data-controller="sortable" data-parent-id="1">
<div class="border p-3" data-url-value="https://csszero.lazaronixon.com/sortables/10">Item 1</div>
<div class="border p-3" data-url-value="https://csszero.lazaronixon.com/sortables/11">Item 2</div>
<div class="border p-3" data-url-value="https://csszero.lazaronixon.com/sortables/12">Item 3</div>
<div class="border p-3" data-url-value="https://csszero.lazaronixon.com/sortables/13">Item 4</div>
<div class="border p-3" data-url-value="https://csszero.lazaronixon.com/sortables/14">Item 5</div>
<div class="border p-3" data-url-value="https://csszero.lazaronixon.com/sortables/15">Item 6</div>
</div>
1
2
3
4
5
6
7
8
<div class="card flex flex-col gap" style="max-inline-size: 400px" data-controller="sortable" data-parent-id="1">
<%= tag.div "Item 1", class: "border p-3", data: { url_value: main_app.sortable_url(10) } %>
<%= tag.div "Item 2", class: "border p-3", data: { url_value: main_app.sortable_url(11) } %>
<%= tag.div "Item 3", class: "border p-3", data: { url_value: main_app.sortable_url(12) } %>
<%= tag.div "Item 4", class: "border p-3", data: { url_value: main_app.sortable_url(13) } %>
<%= tag.div "Item 5", class: "border p-3", data: { url_value: main_app.sortable_url(14) } %>
<%= tag.div "Item 6", class: "border p-3", data: { url_value: main_app.sortable_url(15) } %>
</div>
CSS is not required or multiple files are needed, check the notes.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import { Controller } from "@hotwired/stimulus"
import { put } from "https://cdn.skypack.dev/@rails/request.js@0.0.11?min"
import Sortable from "https://cdn.skypack.dev/sortablejs?min"
export default class extends Controller {
static values = { url: String, group: String, handle: String }
connect() {
this.sortable = new Sortable(this.element, this.#options)
}
disconnect() {
this.sortable.destroy()
}
#submit({ item, newIndex, to }) {
put(item.dataset.urlValue, { query: { position: newIndex, parent_id: to.dataset.parentId } })
}
get #options() {
return { animation: 150, onAdd: this.#submit, onUpdate: this.#submit, group: this.groupValue, handle: this.handleValue }
}
}