sergio

sergio

What's a great modern drag and drop javascript library you recommend?

Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browsers. Modern browsers may have shiny new API’s that are not being leveraged by older plugins.

What’s a great, modern drag and drop plugin you would recommend?

One feature I’m trying to build: I’m trying to replicate the Trello list drag and drop feature where you can drag cards between lists, and drag the lists around as well.

One plugin I found is draggable by Shopify: Draggable JS – JavaScript drag and drop library But it’s not maintained anymore, and has a ton of open PRs.

Another plugin is Sortable: GitHub - SortableJS/Sortable: Reorderable drag-and-drop lists for modern browsers and touch devices. No jQuery or framework required. · GitHub

Thanks!

Most Liked

tlietz

tlietz

After many hours of research, I have finally found a dnd library that is built for vanillajs first, is actually performant (uses webworkers), has a good auto scroll out of the box, and is used in production applications:

Additionally, it doesn’t use the native drag and drop web api, which means that it doesn’t over-scroll in a glitchy way on mobile, and the dragged element can be constrained to a certain axis since it doesn’t need to follow the cursor.

It’s more of a layout engine, but there are Kanban examples that can easily be pared down to do what scrollablejs does.

TwistingTwists

TwistingTwists

This blog uses sortableJS.
I haven’t used it personally, but if fly people are using it, makes me biased already.

slouchpie

slouchpie

I was looking at Muuri today and trying to get the Kanban example working. Examples | Muuri Docs It took me some time to turn the CSS into tailwind and break the HTML into small functions so I am pasting what I did here. Hopefully it helps somebody else get started with Muuri + Phoenix.

defmodule MyAppWeb.MuuriLive.Kanban do
  @moduledoc false
  use MyAppWeb, :html

  def kanban(assigns) do
    ~H"""
    <div id="muuri-kanban-demo" phx-hook="KanbanHook">
      <div class={["drag-container", "fixed top-0 left-0", "z-[1000]"]}></div>
      <div class={["board", "relative"]}>
        <.board_column header="Todo" indexes={1..5} />
        <.board_column header="Working" indexes={6..10} />
        <.board_column header="Done" indexes={11..15} />
      </div>
    </div>
    """
  end

  attr :header, :string
  attr :indexes, :integer

  defp board_column(assigns) do
    ~H"""
    <div class={[
      "board-column done",
      "absolute top-0 left-0",
      "py-0 px-[10px]",
      "w-1/3",
      "z-[1] muuri-item-releasing:z-[2] muuri-item-dragging:z-[3] muuri-item-dragging:cursor-move"
    ]}>
      <div class={[
        "board-column-container",
        "w-full h-full"
      ]}>
        <div class={[
          "board-column-header",
          "relative",
          "h-[50px] leading-[50px]",
          "overflow-hidden",
          "py-0 px-[20px]",
          "text-center",
          "bg-green-500",
          "text-white",
          "rounded-sm",
          "font-bold",
          "tracking-[0.5px]",
          "uppercase"
        ]}>
          <%= @header %>
        </div>
        <div class={[
          "board-column-content-wrapper",
          "relative",
          "p-[8px]",
          "bg-blue-700",
          "h-screen",
          "overflow-y-auto",
          "rounded-sm"
        ]}>
          <div class={["board-column-content", "relative min-h-full"]}>
            <.board_item :for={index <- @indexes} index={index} />
          </div>
        </div>
      </div>
    </div>
    """
  end

  attr :index, :integer

  defp board_item(assigns) do
    ~H"""
    <div class={[
      "board-item",
      "absolute w-full m-[8px]",
      "muuri-item-releasing:z-[9998] muuri-item-dragging:z-[9999]",
      "muuri-item-dragging:cursor-move",
      "muuri-item-hidden:z-[0]"
    ]}>
      <div class={[
        "board-item-content",
        "relative p-[20px]",
        "bg-white",
        "rounded-[4px]",
        "text-[17px]",
        "cursor-pointer"
      ]}>
        <span>Item #</span><%= @index %>
      </div>
    </div>
    """
  end
end

and the hook

import Muuri from "../../vendor/muuri";

const KanbanHook = {
  mounted() {
    var dragContainer = document.querySelector(".drag-container");
    var itemContainers = [].slice.call(
      document.querySelectorAll(".board-column-content"),
    );
    var columnGrids = [];
    var boardGrid;

    // Init the column grids so we can drag those items around.
    itemContainers.forEach(function (container) {
      var grid = new Muuri(container, {
        items: ".board-item",
        dragEnabled: true,
        dragSort: function () {
          return columnGrids;
        },
        dragContainer: dragContainer,
        dragAutoScroll: {
          targets: (item) => {
            return [
              { element: window, priority: 0 },
              { element: item.getGrid().getElement().parentNode, priority: 1 },
            ];
          },
        },
      })
        .on("dragInit", function (item) {
          item.getElement().style.width = item.getWidth() + "px";
          item.getElement().style.height = item.getHeight() + "px";
        })
        .on("dragReleaseEnd", function (item) {
          item.getElement().style.width = "";
          item.getElement().style.height = "";
          item.getGrid().refreshItems([item]);
        })
        .on("layoutStart", function () {
          boardGrid.refreshItems().layout();
        });

      columnGrids.push(grid);
    });

    // Init board grid so we can drag those columns around.
    boardGrid = new Muuri(".board", {
      dragEnabled: true,
      dragHandle: ".board-column-header",
    });
  },
};
export { KanbanHook };

I will be changing the JS to use this.el. For now, it is identical to the JS given in their example.

It works nice. It “feels” better than sortable, which was my go-to for drag-n-drop

The tailwind modifiers I added like this:

    plugin(({ addVariant }) => addVariant("muuri", [".muuri&", ".muuri &"])),
    plugin(({ addVariant }) => addVariant("muuri", [".muuri&", ".muuri &"])),
    plugin(({ addVariant }) =>
      addVariant("muuri-item", [".muuri-item&", ".muuri-item &"]),
    ),
    plugin(({ addVariant }) =>
      addVariant("muuri-item-shown", [
        ".muuri-item-shown&",
        ".muuri-item-shown &",
      ]),
    ),
    plugin(({ addVariant }) =>
      addVariant("muuri-item-hidden", [
        ".muuri-item-hidden&",
        ".muuri-item-hidden &",
      ]),
    ),
    plugin(({ addVariant }) =>
      addVariant("muuri-item-positioning", [
        ".muuri-item-positioning&",
        ".muuri-item-positioning &",
      ]),
    ),
    plugin(({ addVariant }) =>
      addVariant("muuri-item-dragging", [
        ".muuri-item-dragging&",
        ".muuri-item-dragging &",
      ]),
    ),
    plugin(({ addVariant }) =>
      addVariant("muuri-item-releasing", [
        ".muuri-item-releasing&",
        ".muuri-item-releasing &",
      ]),
    ),
    plugin(({ addVariant }) =>
      addVariant("muuri-item-placeholder", [
        ".muuri-item-placeholder&",
        ".muuri-item-placeholder &",
      ]),
    ),

in tailwind config js.

Where Next?

Popular in Discussions Top

matthias_toepp
I’d love to hear what people think about Wisp, the new Gleam web framework started by Gleam’s primary creator Louis Pilfold. Gleam, alon...
New
pillaiindu
In django there is a cache framework backed by memcached. Rails also puts a lot of emphasis on caching, and even the idea of russian-doll...
New
mmmrrr
Just saw that dhh announced https://hotwire.dev/ Is it just me or is this essentially live view? :smiley: Although I like the “iFrame-e...
New
nburkley
AWS re:Invent is on at the moment with some interesting announcements. One new feature in particular is the Lambda Runtime API for AWS La...
New
PragTob
Hey everyone, this has been brewing in my head some time and it came up again while reading Adopting Elixir. GenServers, supervisors et...
New
boundedvariable
I am going through the kafka architecture. All the features what the kafka is providing are already in Erlang. I would like hear your opi...
New
rms.mrcs
A couple of days ago I was discussing with a friend about different approaches to write microservices. He said that if he was going to w...
New
chulkilee
Here are the list of HTTP client libraries/wrappers, and some thoughts on HTTP client in general. I’d like to hear from others how they w...
New
scouten
I’m looking for a host for the server part of a small (personal) side project that I’m working on. It’s currently written in Node.js and ...
New
pdgonzalez872
If this has been asked here before, please point me to where it was asked as I didn’t find it when I searched the forum. Maybe a mailing ...
New

Other popular topics Top

sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 29603 241
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 36352 110
New
komlanvi
Hi everyone, I was playing with phoenix liveView but I run into an issue. I have a form and want to validate each input text when the te...
New
axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 48342 226
New
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement