Sortable

Demonstrates how to use htmx with the Sortable.js plugin to implement drag-and-drop reordering

HOME | Explain | Code | Htmx Docs | Full screen
In this example we show how to integrate the Sortable javascript library with htmx. To begin we initialize the `.sortable` class with the Sortable javascript library. This is done automatically by fasthtml SortableJS implementation. ```python app, rt = fast_app(hdrs=[SortableJS()]) ``` Next, we create a form that has some sortable divs within it, and we trigger an ajax request on the end event, fired by Sortable.js: ``` @app.get def page(): return ( Form(cls="sortable", hx_post="/items", hx_target="#logs", hx_trigger="end")( Div(cls="htmx-indicator")("Updating..."), *[Article(Input(type="hidden", name="item", value=i), f"Item {i}") for i in range(1, 6)], ), Div(id="logs"), ) ``` Note that each div has a hidden input inside of it that specifies the item id for that row. When the list is reordered via the Sortable.js drag-and-drop, the end event will be fired. htmx will then post the item ids in the new order to /items, to be persisted by the server. That’s it! If you do not use fasthtml SortableJS implementation, you can add the following script to your headers: <details> <summary role="button">If you do not use fasthtml SortableJS</summary> ```javascript htmx.onLoad(function(content) { var sortables = content.querySelectorAll(".sortable"); for (var i = 0; i < sortables.length; i++) { var sortable = sortables[i]; var sortableInstance = new Sortable(sortable, { animation: 150, ghostClass: 'blue-background-class', // Make the `.htmx-indicator` unsortable filter: ".htmx-indicator", onMove: function (evt) { return evt.related.className.indexOf('htmx-indicator') === -1; }, // Disable sorting on the `end` event onEnd: function (evt) { this.option("disabled", true); } }); // Re-enable sorting on the `htmx:afterSwap` event sortable.addEventListener("htmx:afterSwap", function() { sortableInstance.option("disabled", false); }); } }) ``` </details>

Server Calls