1

I have two tables and I am able to drag and drop multiple elements using sortable. My problem is that when I drag items from table2 sometimes in table1, ui.item.index() returns -1.

After some tests I found that the problem is the initial position of the drag. If I start dragging in table2 index 0, everything works fine. see image

But if I start dragging from any other position (e.g. 2), ui.item.index() returns -1 enter image description here

It is a tricky problem and I can not reproduce it on a test environment. I leave part of my code below if It helps:

$("#table1 tbody").sortable({
    connectWith: "#table2 tbody",
    helper: function (e, item) {
      const $helper = $("<div/>");
      const $originals = item.children();

      // Select the row that user is moving
      table1Api.row(item).select();

      const data = item.parent().children(":has(input:checked)").clone();
      matchHelperSizeToOriginal(data, $originals);

      // Hide siblings with checked inputs & storing the data
      item.data("data", data).siblings(":has(input:checked)").hide();

      return $helper.append(data);
    },
    start: function (e, ui) {
      const data = ui.item.data("data");
      ui.helper.append(data);
    },
    stop: function (e, ui) {
      // irrelevant code here
    },
    receive: function (e, ui) {
      const data = ui.item.data("data");
      let newIndex = ui.item.index(); // returns -1
      console.log(newIndex);
      for (const d of data) {
        table1.row().add(d).draw();
      }
    },
    remove: function (e, ui) {
      const data = ui.item.data("data");
      for (const d of data) {
        table2.row(d).remove().draw();
      }
    },
    axis: "xy",
    cursor: "grabbing",
  });
$("#table2 tbody").sortable({
    connectWith: "#table1 tbody",
    items: "tr:not(:has(.dataTables_empty))",
    helper: function (e, item) {
      const $helper = $("<div/>");
      const $originals = item.children();

      // Select the row that user is moving
      table2Api.row(item).select();

      const data = item.parent().children(":has(input:checked)").clone();
      matchHelperSizeToOriginal(data, $originals);

      // Hide siblings with checked inputs & storing the data
      item.data("data", data).siblings(":has(input:checked)").hide();

      return $helper.append(data);
    },
    start: function (e, ui) {
      const data = ui.item.data("data");
      ui.helper.append(data);
    },
    stop: function (e, ui) {
      ui.item.siblings(":hidden").show();
    },
    receive: function (e, ui) {
      const data = ui.item.data("data");
      for (const d of data) {
        table2.row().add(d).draw();
      }
    },
    remove: function (e, ui) {
      const data = ui.item.data("data");
      for (const d of data) {
        table2.row(d).remove().draw();
      }
    },
    axis: "xy",
    cursor: "grabbing",
  });
0

1 Answer 1

1

I just found the problem. In the remove event of table2 I was deleting my data from table2 and updating the display inside the loop.

remove: function (e, ui) {
   const data = ui.item.data("data");
   for (const d of data) {
     table2.row(d).remove().draw();
   }
},

Drawing the table out of the loop solves the issue.

remove: function (e, ui) {
   const data = ui.item.data("data");
   for (const d of data) {
     table2.row(d).remove();
   }
   table2.rows().draw()
},
1

Not the answer you're looking for? Browse other questions tagged or ask your own question.