Preserving row attributes / proper row reordering

Preserving row attributes / proper row reordering

ilyakapitanilyakapitan Posts: 8Questions: 3Answers: 0
edited March 2017 in Free community support

To start, RowReorder extension has an issue in the process of reorder. Actually I have 2 issues, 1 is connected to row reorder the other one is with keeping attributes on row. I'll explain.

When you reorder, it does move rows around and change the number of row, but the actual index is not changed.

I have a function that when I click on a button in row, the row between gets added, I use a for loop that gets the index of element where I clicked, adds a row to the datatable and starts moving it around to desired position:

[0][1][2][3][4->][<-newRow]
[0][1][2][3->][<-newRow][4]
[0][1][2->][<-newRow][3][4]
 insertedRow = table.row(rowCount).node(),
                insertedRowData = table.row(insertedRow).data(),
                tempRow,
                rowCount = table.data().length-1
                tempRowData;

            //move added row to desired index
            for (var i=rowCount;i>index+1;i--) {
                tempRow = table.row(i-1).node();
                tempRowData = table.row(tempRow).data();
                table.row(i).data(tempRowData);
                table.cell(i,0).data(i+1);
                table.row(i-1).data(insertedRowData);
            }

To add a row between I need to get the index of a row on which I clicked, I get it by using:
index = table.row(el).index();
So let's say I have 4 rows, I drag the last one to second position and when I click on it, to add a row between it will actually add a row to the 5th position, because when row reorder is over the index is still 4 even tho in html it will say 2.

To fix that I turned off the update in rowReorder

rowReorder: {
                    snapX: 7,
                    update: false
                },

And on row-reorder event I added

for (var i=diff.length - 1; i>=0; i--) {
                    diff[i].nodeData = table.row(diff[i].node).data();
                }

                for (var i = table.data().length-1; i >= 0; i--) {
                    for (var j = diff.length - 1; j >= 0; j--) {
                        if(i === diff[j].newPosition) {
                            table.row(i).data(diff[j].nodeData);
                            table.cell(i,0).data(diff[j].newData);
                            i--;
                        }
                    }
                }

Which is pretty similar to my row between loop. It works nicely, but the thing is, that I have different html attributes on row and I need to move them along, but since all those functions affect only the inner data, I can't achieve this.

I wrote a copyAttribute function for my rowReorder and rowBetween:

$.fn.copyAllAttributes = function (sourceElement, erase, copyClass, ignoreAttr) {
        erase = erase || false;
        copyClass = copyClass || false;
        ignoreAttr = ignoreAttr || '';

        // 'that' contains a pointer to the destination element
        var that = this;

        // Place holder for all attributes
        var allAttributes = $(sourceElement).prop("attributes"),
            attrString = '';

        if (allAttributes && that.length == 1) {
            $.each(allAttributes, function () {
                // Ensure that class names are not copied but rather added
                if(this.name == "class"){
                    copyClass ? that.addClass(this.value) : 0;
                } else if (ignoreAttr.indexOf(this.name) == -1){
                    that.attr(this.name, this.value);
                    attrString += ' ';
                    attrString += this.name;
                }
            });

            erase ? $(sourceElement).removeAttr(attrString) :0; // bug
        }
        return that;
    };

But they are preserved only until datatable has to manipulate the html again, as soon as it happens everything is like cache reverted or changed...

Any advice how can I keep my attributes and move them along? This is what I'm interested in the most, rowReorder itself can be left the way it is.

Test case -> jsFiddle

Answers

  • ilyakapitanilyakapitan Posts: 8Questions: 3Answers: 0

    Any update with this? I really need some solution to this...

  • bindridbindrid Posts: 730Questions: 0Answers: 119

    Your test case on jsFilddle has an error in it.

    $(table.table().body()).on('click', '[data-action="addRow"]', function() {
        // table.row(this.closest('tr')).invalidate().draw(false);
        itemBetween(this.closest('tr'));
      });
    

    In this context "this" is an element not a jquery object so closest will not work.
    try $(this).closest("tr")

  • allanallan Posts: 63,761Questions: 1Answers: 10,510 Site admin

    One thing to keep in mind is that RowReorder implements as value swap mechanism for the ordering. It does not simply move elements around the page like jQuery UI Sortable.

    The order of the rows in the table is always defined by the ordering applied to the DataTable and the data in the columns being ordered.

    Consider this example.

    If you open the console in your browser and run:

    $('#example').DataTable().row(':eq(0)').node().setAttribute( 'data-test', 'hello world' );
    

    That will add an attribute to the first row in the table. Reorder the rows so the first row moves down and the attribute will move with it.

    Allan

  • ilyakapitanilyakapitan Posts: 8Questions: 3Answers: 0

    @bindrid, good point, made a mistake when creating the case, but it doesn't affect my problem. Updated case -> jsFiddle

    @allan Yes, RowReorder does the full value swap, I noticed that when was doing my solution. The problem with it was, that even tho all the elements data gets swapped and index updated, it's not actually updated in .data(). So when I was trying to add the row "between" I was getting an old index so the inserted spot was always wrong. That's why I created my own data swap.

    But apparently I need to do DOM swap somehow as well, since I'm moving data around not only with RowReorder but also when adding the row between and doing table reordering.
    I tried to extract the functionality from RowReorder to expand my solution, but so far I wasn't able to succeed, maybe I'm not smart enough.

    So I was hoping that maybe you'd be able to lend me a hand to make a proper internal/external data swap.

  • allanallan Posts: 63,761Questions: 1Answers: 10,510 Site admin

    I'm afraid I'm not quite getting it - particularly this point:

    it's not actually updated in .data()

    If you go to this page and in the console enter:

    $('#example').DataTable().row(':eq(0)').data()
    

    it will show:

    ["1", "Shou Itou", "Regional Marketing", "Tokyo", "2011/08/14", "$163,000"]

    Now swap the second row with the first one and run that same console line again. Now it will show:

    ["1", "Tiger Nixon", "System Architect", "Edinburgh", "2011/04/25", "$320,800"]

    The data for the row has changed. The sequence number hasn't - that's the data swap.

    Are you able to explain what you want to happen using that simple test case?

    Thanks,
    Allan

  • ilyakapitanilyakapitan Posts: 8Questions: 3Answers: 0

    @allan right, you are correct actually. Explained it in a wrong way. To add a row between (for example) I had to get an index of an element that I clicked on, so after RowReorder this line table.row(el).index() will give an old index. I guess that's what you mean by the sequence number.

    In my solution, I have different manipulations with rows: RowBetween, RowReorder and Table Reorder. In all of those cases I need to update the sequence number as well, because row between needs to be appended into proper position (for example). When I'm doing table reorder I'm updating the sequence as well, because in my case the solution is basically a "table of products" which means if I'm doing a table reorder it later will have to be saved in this order, not just giving me a "sorting" possibility.

    I don't know about the quality of my written code, but so far everything is working exactly as I expect, indexes get updated and data gets moved, all good, except HTML attributes which I can't move either because of my lack of knowledge or because of the slightly wrong approach.

This discussion has been closed.