Move draggable items between columns and save position
Asked Answered
L

2

6

I have a bunch of users that are represented by the gray boxes. I would like to move these users from one column to another (light blue). Each column represents a different status of the user.

enter image description here

The draggable (https://github.com/Shopify/draggable) function is already working, and I can get the source location and item id that was dragged. But I can not figure out how to get the information of the destination column.

Here is my code so far:

var containers = document.querySelectorAll(".draggable-zone");

    if (containers.length === 0) {
        return false;
    }

    var swappable = new Sortable.default(containers, {
        draggable: ".draggable",
        handle: ".draggable .draggable-handle",
        mirror: {
            //appendTo: selector,
            constrainDimensions: true
        }
    });

    swappable.on('drag:start', (event) => {
        // works
    });

    swappable.on('drag:stop', (event) => {
        console.log(event);
        console.log(event.source.id); // return user id
        console.log(event.sourceContainer.id); // return source column id (status)
    });
<script src="https://cdn.jsdelivr.net/npm/@shopify/[email protected]/lib/draggable.bundle.js"></script>
<div class="content d-flex flex-column flex-column-fluid" id="">
    <div class="container-fluid" id="">
        <div class="col-xs-12 no-padding s-row" style="display: flex;overflow-x: auto;">
            <div id="col_1" class="draggable-zone col-xs-12 col-md-3 p-2 m-2" style="background-color: lightblue">
                <h3>Col 1</h3>
                <!-- start::draggable user item -->
                <div id="user_1" class="draggable text-white rounded p-3 m-1 mb-3 h-100px" style="background-color: lightslategray">
                    User 1
                    <div class="draggable-handle">X</div>
                </div>
                <!-- end::draggable user item -->
                <!-- start::draggable user item -->
                <div id="user_2" class="draggable text-white rounded p-3 m-1 mb-3 h-100px" style="background-color: lightslategray">
                    User 2
                    <div class="draggable-handle">X</div>
                </div>
                <!-- end::draggable user item -->
                <!-- start::draggable user item -->
                <div id="user_3" class="draggable text-white rounded p-3 m-1 mb-3 h-100px" style="background-color: lightslategray">
                    User 3
                    <div class="draggable-handle">X</div>
                </div>
                <!-- end::draggable user item -->
                <!-- start::draggable user item -->
                <div id="user_4" class="draggable text-white rounded p-3 m-1 mb-3 h-100px" style="background-color: lightslategray">
                    User 4
                    <div class="draggable-handle">X</div>
                </div>
                <!-- end::draggable user item -->
            </div>
            <!-- end::col -->
            <!-- start::col -->
            <div id="col_2" class="draggable-zone col-xs-12 col-md-3  p-2 m-2" style="background-color: lightblue">
                <h3>Col 2</h3>
                <!-- start::draggable user item -->
                <div id="user_5" class="draggable text-white rounded p-3 m-1 mb-3 h-100px" style="background-color: lightslategray">
                    User 5
                    <div class="draggable-handle">X</div>
                </div>
                <!-- end::draggable user item -->
                <!-- start::draggable user item -->
                <div id="user_6" class="draggable text-white rounded p-3 m-1 mb-3 h-100px" style="background-color: lightslategray">
                    User 6
                    <div class="draggable-handle">X</div>
                </div>
                <!-- end::draggable user item -->
                <!-- start::draggable user item -->
                <div id="user_7" class="draggable text-white rounded p-3 m-1 mb-3 h-100px" style="background-color: lightslategray">
                    User 7
                    <div class="draggable-handle">X</div>
                </div>
                <!-- end::draggable user item -->
            </div>
            <!-- end::col -->
            <!-- start::col -->
            <div id="col_3" class="draggable-zone col-xs-12 col-md-3  p-2 m-2" style="background-color: lightblue">
                <h3>Col 3</h3>
            </div>
            <!-- end::col -->
            <!-- start::col -->
            <div id="col_4" class="draggable-zone col-xs-12 col-md-3  p-2 m-2" style="background-color: lightblue">
                <h3>Col 4</h3>
            </div>
            <!-- end::col -->
            <!-- start::col -->
            <div id="col_5" class="draggable-zone col-xs-12 col-md-3  p-2 m-2" style="background-color: lightblue">
                <h3>Col 5</h3>
                <!-- start::draggable user item -->
                <div id="user_8" class="draggable text-white rounded p-3 mb-3 m-1 h-100px" style="background-color: lightslategray">
                    User 8
                    <div class="draggable-handle">X</div>
                </div>
                <!-- end::draggable user item -->
                <!-- start::draggable user item -->
                <div id="user_9" class="draggable text-white rounded p-3 mb-3 m-1 h-100px" style="background-color: lightslategray">
                    User 9
                    <div class="draggable-handle">X</div>
                </div>
                <!-- end::draggable user item -->
            </div>
            <!-- end::col -->
            <!-- start::col -->
            <div id="col_6" class="draggable-zone col-xs-12 col-md-3  p-2 m-2" style="background-color: lightblue">
                <h3>Col 6</h3>
            </div>
            <!-- end::col -->
        </div>
    </div>
</div>

In addition I would like also to save the order of the user in each column.

May be some can help me out.

Any help is appreciated.

Best regards

Tim

Lanthanide answered 25/7, 2022 at 15:55 Comment(4)
Same problem here brother!Platitudinous
Wait, I'll add a bounty on this questionPlatitudinous
The snippet does not work. Can you, Tim (or Jishnu Raj) provide a reproducible snippet?Deadly
Please elaborate more about your issue along with the working code.Lambard
D
2

Solution

based on [email protected]

Binding Javascript Data to DOM

to bind internal data to a DOM element, use data attribute.

// data-column exposes the bound data of given element
<div class="column" data-column="1" />

column data is accessible with this data attribute.

Dynamically Save and Reconstruct Status

Try build the DOM structure with a given data, not with static HTML code. So that the item state can be reconstructed later with modified data.

<div id="root">
  <div class="col" data-column="0">col0</div>
  <div class="col" data-column="1">col1</div>
  <div class="col" data-column="2">col2</div>
</div>

// use data to dynamically reconstruct the items
const items = [
  { column: 0, label: "aaa", index: "a" },
  { column: 1, label: "bbb", index: "b" },
  { column: 1, label: "ccc", index: "c" }
];

function init() {
  const root = document.getElementById("root");
  const columns = document.querySelectorAll("#root .col");
  const divItems = items.map((item) => {
    const divItem = document.createElement("div");
    divItem.setAttribute("class", "draggable item");
    divItem.setAttribute("data-index", item.index);
    divItem.innerHTML = item.label;
}
init();

Getting Column Data from Draggable.Sortable Event

Draggable exposes all necessary DOM elements. Utilize the data attribute to get column data.

const sortable = new Sortable(columns, { draggable: ".draggable" });
  sortable.on("sortable:stop", (ev) => {
    const newCol = ev.data.newContainer.getAttribute("data-column");
    const oldCol = ev.data.oldContainer.getAttribute("data-column");
    const index = ev.data.dragEvent.data.source.getAttribute("data-index");
    // mutate items data with data acquired from DOM attribute
    console.log({ index, newCol, oldCol });
    // i.g. var idx = items.findIndex(i => i.index === index); items[idx].column = newCol;
  });

demo available at codepen. check browser console.

Demiurge answered 11/10, 2022 at 10:5 Comment(0)
G
0
swappable.on('drag:stop', (event) => {
      console.log(event);
      console.log(event.originalSource.parentNode.id); // return current col id
  });

No code changes are required, the originalSource is returned with whatever information you want :D

Gamine answered 18/10, 2022 at 7:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.