*BUG* DataTables RowReorder - Clears data from new rows

*BUG* DataTables RowReorder - Clears data from new rows

jLinuxjLinux Posts: 981Questions: 73Answers: 75
edited September 2015 in Free community support

I have a DataTables table inside a web form, each row is a new record of whats being created, every td has an <input> of some sort (select, checkbox, radio, input, etc). The table starts off with one row in it, and you can add new rows to the table by clicking an add row button.

You can re-order the rows by dragging them, which I thought was working fine, until I tried to re-order rows that are being added new.

When you populate the inputs, then drag the row to re-order it, once its re-ordered, it will clear all of the data out..

I actually went as far as to create my first live.datatables.net instance :-O

http://live.datatables.net/mefaluwi/2/edit?html,js,output

Just add a few rows, populate the inputs, and re-order the rows..
It should automatically add the first row when the page loads, so if you dont see a row with inputs, then refresh the page. I had to do that once or twice to get everything fully loaded

Thanks!

Edited DTL, to show it is an issue with all inputs... radio, checkbox, textarea, string

Answers

  • jLinuxjLinux Posts: 981Questions: 73Answers: 75

    And quick question about the Live DT page, how do I stop it from re-generating the code on every single keystroke? It causes a lot of issues, for example, if im in the HTML column, and start typing an <input> tag, it will throw an error until the tag is closed.. Realllly annoying. I had to code it locally then paste it in the DTL Instance

  • allanallan Posts: 61,822Questions: 1Answers: 10,129 Site admin
    Answer ✓

    And quick question about the Live DT page, how do I stop it from re-generating the code on every single keystroke?

    Hit the "Auto-run JS" checkbox in the top right. It is a bit of a pain that.

    Interesting bug you've found there - the data is retained while the row is being dragged, but when dropped it is cleared.

    What is happening is that RowReorder is calling row().invalidate() when the row is dropped. That causes DataTables to read the data from the data source again and draw it into the table.It should perhaps try to invalidate only the cell that contains the sequence rather than the whole row. I'll look into that.

    Thanks,
    Allan

  • jLinuxjLinux Posts: 981Questions: 73Answers: 75

    Ok, glad to know it wasnt something I did, hah.

    Also glad I can point these out to help! I havent updated the js/css files lately, so when this is fixed, ill update it to fix the scrolling issue too

  • allanallan Posts: 61,822Questions: 1Answers: 10,129 Site admin

    I can't promise that this will be fixed in the near future unfortunately. I'll try to look at it, but there is quite a back log of things to do atm.

    Allan

  • jLinuxjLinux Posts: 981Questions: 73Answers: 75
    edited September 2015

    Oh. My app kinda depends on it. Any quick work around i can do? Even if i need to mess with the dt source for now. Can i disable the invalidate or apply it to only find('td').eq(1) ?

    Or you said it repulls it from the source, which in my case is the dom, van i do something after each input is changed to update the data source content?

  • allanallan Posts: 61,822Questions: 1Answers: 10,129 Site admin

    If it is a priority for you, there is priority support available which would promote it up my todo list. Alternatively, if you have a look in the RowReorder code for where it calls the invalidate function, that is where it needs to be updated to invalidate the cell rather than the row - but I haven't looked in detail at exactly what is required yet.

    Allan

  • jLinuxjLinux Posts: 981Questions: 73Answers: 75

    PM'd!

  • jLinuxjLinux Posts: 981Questions: 73Answers: 75

    Is there an easy way to have DataTables re-cache the DOM source? If so, I can just do that right before the row-reorder, that would be easiest, imo

  • allanallan Posts: 61,822Questions: 1Answers: 10,129 Site admin

    The invalidate method will do that, but I'm not sure it will help in this case to be honest since the data is modified once the row has been moved.

    Allan

  • allanallan Posts: 61,822Questions: 1Answers: 10,129 Site admin
    Answer ✓

    Its taken an embarrassing amount of time to get to this, but I've finally committed the required change. It will be in the next RowReorder release and the nightly builds are up-to-date with this change already.

    Allan

  • jLinuxjLinux Posts: 981Questions: 73Answers: 75
    edited November 2015

    Thanks!!

    Curious how you fixed it, ill take a look

  • allanallan Posts: 61,822Questions: 1Answers: 10,129 Site admin
    Answer ✓

    Basically do cell invalidation rather than row invalidation. Used the column().dataSrc() method to match the column to invalidate with the RowReorder data property.

    Allan

  • jLinuxjLinux Posts: 981Questions: 73Answers: 75

    Basically just this part:

    // Invalidate the cell that has the same data source as the dataSrc
    dt.columns().every( function () {
        if ( this.dataSrc() === dataSrc ) {
            dt.cell( fullDiff[i].node, this.index() ).invalidate( 'data' );
        }
    } );
    

    So if the content of the cell is the same as the data source, its invalidated.. But doesn't invalidating just set the content back to what the source was? If so, whats the point of invalidating the cell if you know the content is the same as the invalidated content?

    Im just curious, I like to know how these things work :-D

  • allanallan Posts: 61,822Questions: 1Answers: 10,129 Site admin

    But doesn't invalidating just set the content back to what the source was?

    The data for the cell was modified the line up from that:

    setDataFn( rowData, fullDiff[i].newData );
    

    So the cell().invalidate( 'data' ) tells DataTables that the data has changed and it should re-read the data source for its cache and update the DOM display.

    You could use cell().invalidate( 'dom' ) to read from the DOM rather than the data (or no parameter to have DataTables auto detect the original data source), which can be useful in some cases, but not here.

    So in this case the data has changed and hence it needs to be invalidated.

    Allan

  • jLinuxjLinux Posts: 981Questions: 73Answers: 75

    So in this case the data has changed and hence it needs to be invalidated.

    Right, maybe im just confused, because arent you checking if the data HASNT changed? (===), then invalidating those?

        if ( this.dataSrc() === dataSrc ) {
            dt.cell( fullDiff[i].node, this.index() ).invalidate( 'data' );
        }
    

    Again, not that any of this matters, you say it works, thats good enough.

  • allanallan Posts: 61,822Questions: 1Answers: 10,129 Site admin
    edited November 2015 Answer ✓

    Ah - but my check there is not for the data, but for the data source. For example if I use {data: 'name'} to tell a column where to get the data from (columns.data) then column().dataSrc() will be simply name. It will not be the data (regardless of the value of the data).

    edit So I'm checking to see if the column contains the data that was changed. The other option would be to require the column index to be passed in, but this is easier if slightly less robust, for users.

    Allan

  • jLinuxjLinux Posts: 981Questions: 73Answers: 75

    I realized it was the data source, I guess I was just a little lost, but thanks! Glad you got it working, as always

This discussion has been closed.