Skip to content

Instantly share code, notes, and snippets.

@somazx
Created March 29, 2023 13:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save somazx/48979e31ebb6025c3c7ac27068258c03 to your computer and use it in GitHub Desktop.
Save somazx/48979e31ebb6025c3c7ac27068258c03 to your computer and use it in GitHub Desktop.
Orderable: Drag & Drop Ordering - Stimulus Controller
import { Controller } from "stimulus";
// Handles ordering elements on the page using
// buttons than can move the elements up or down.
//
// Usage:
// 1. Add data-controller orderable on a parent node.
// 2. (Optional) For persisting order to input fields:
// - add data-orderable-target="orderInput"
// 3. Wire up buttons or links to call up/down actions.
// by adding data-action="orderable#up", or
// data-action="orderable#dowm"
const MOVES = {
down: {
sibling: 1,
insert: "afterend",
},
up: {
sibling: -1,
insert: "beforebegin",
},
};
export default class extends Controller {
static targets = ["orderInput", "orderable"];
connect() {
this.setOrder();
}
move(target, direction) {
this.orderableTargets.length;
const targetIndex = this.orderableTargets.findIndex(t => t === target);
const swapTarget = this.orderableTargets[
targetIndex + MOVES[direction].sibling
];
if (target && swapTarget) {
swapTarget.insertAdjacentElement(MOVES[direction].insert, target);
this.setOrder();
}
}
up({ currentTarget }) {
this.move(this.getTarget(currentTarget), "up");
}
down({ currentTarget }) {
this.move(this.getTarget(currentTarget), "down");
}
reorder() {
setTimeout(() => this.setOrder(), 100);
}
getTarget(currentTarget) {
return currentTarget.closest("[data-orderable-target]");
}
setOrder() {
this.orderInputTargets.forEach(
(targetInput, index) => (targetInput.value = index)
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment