Help figuring out how to flash a row updated via ajax

Help figuring out how to flash a row updated via ajax

zthomaszthomas Posts: 10Questions: 2Answers: 0

Link to test case: https://live.datatables.net/bepedisi/1/
I do not know how to set up a test cast to function with ajax, the above just has the default data loaded via plain html.
Debugger code (debug.datatables.net): None
Error messages shown: None
Description of problem:
I am trying to figure out how I can flash rows in my table that are updated. The above example technically accomplishes that I suppose, but what actually happens is every time the ajax reload happens the entire table flashes. What I want to happen is for a row to flash only if any of the data in the row is different than it was before the ajax reload. I am very green on frontend programming so if anything I've done is stupid or could be done better, related to my question or not, I am happy to get constructive criticism :)

Thanks!

This question has accepted answers - jump to:

Answers

  • kthorngrenkthorngren Posts: 21,342Questions: 26Answers: 4,954

    This technote provides links to ajax and server side processing JS BIN templates. I took the Ajax Arrays template and pasted the URL into your test case.

    It looks like you are referring to the code in createdRow:

        createdRow: function (row, data, index) {
            $(row).addClass('highlight').fadeOut(500).fadeIn(500, function() {
                $(this).removeClass('highlight');
            });
        }
    

    This will run only when the row is added to the DOM which occurs at initialization and after the ajax.reload().

    For the test case to run I also removed the tbody and change the table ID to status_table.
    https://live.datatables.net/bepedisi/1/edit

    Also changed the setTimeout timer to 6000 to reduce wait time.

    What I want to happen is for a row to flash only if any of the data in the row is different than it was before the ajax reload

    Is there any way to know if the row data is different from the data at the server? For example a flag that is set or a timestamp? If not maybe iterate over the data in the server script to set a flag. If this info can be sent in the ajax response then the createdRow function can be updated to check this field to decide whether to flash or not.

    Otherwise a copy of the fetched data set will need to be kept outside of Datatables so it can be compared to in createdRow. Here is one option:
    https://live.datatables.net/bepedisi/1/edit

    It uses the preXhr event to build an object containing the table data before the ajax.reload() request is sent. It builds an object for easier comparison. The object key is a unique data element from each row. This is stored in the global variable previousData.

    The xhr event is simply for testing to manipulate the ajax.reload() JSON data so that Airi Satou's position is changed each reload.

    The ready() API is used to initiate these events after the Datables has initially loaded the original data set.

    createdRow has been updated to compare the new data to previousData.

    There are lots of ways this could be done. Just depends on your environment and amount of data to determine the best most efficient way.

    Kevin

  • kthorngrenkthorngren Posts: 21,342Questions: 26Answers: 4,954

    I wanted to add that, in general, its much easier to work with objects than arrays in Javascript. See the data docs for details. Instead of accessing the first column using data[0] for example you would use the key of the object. This example uses objects and you would access the name with data.name or data["name"]. Its helpful in that if data[0] becomes data[5] at some point you will need to change your code. With objects the order doesn't matter.

    Kevin

  • zthomaszthomas Posts: 10Questions: 2Answers: 0

    You guys respond so thoroughly and quickly, incredibly impressive!

    I don't think your example links are working for me, both of them that you posted just take me back to the original example I included in my post. Regarding knowing if the data has changed at the server side, I don't know how I would implement that considering that there could be hundreds of users with this page open. I suppose the ajax call would need to send back to the server all of the data it currently has and the server would diff that against what is in the database, then respond with the updated values flagged somehow? That seems inefficient but perhaps (likely) there are ways to improve that exchange I am just unaware of.

    I am interested in the solution you described regarding storing the fetched data to compare in the createdRow function, but I don't know why your links aren't working for me.

  • kthorngrenkthorngren Posts: 21,342Questions: 26Answers: 4,954
    Answer ✓

    Oops it did not save a new link. Luckily I was able to find it in the browser history.
    https://live.datatables.net/caporiva/1/edit

    Kevin

  • kthorngrenkthorngren Posts: 21,342Questions: 26Answers: 4,954

    I wouldn't send the data back to the server either. I was thinking if your data had a timestamp each time it was changed then that could be used to know what has changed. On first load you would keep the latest timestamp then check it in createdRow and keep track of the latest timestamp.

    Kevin

  • zthomaszthomas Posts: 10Questions: 2Answers: 0

    Thanks for the example, I've had some time to look through it and I believe I understand what's going on. One question I do have is why you don't have to use the .dt as mentioned here https://datatables.net/reference/event/preXhr

    I believe that is a simple solution to my problem, I will give it a try and report back!

  • zthomaszthomas Posts: 10Questions: 2Answers: 0

    Also I took your advice and moved to using object instead of array for my data. Is there an object-based way to access my columns now to replace the below or is the only way using the index?

    if (data.status == "up") {
                            $("td:eq(5)", row).addClass("status-up");
                    }
    
  • kthorngrenkthorngren Posts: 21,342Questions: 26Answers: 4,954
    edited June 26

    why you don't have to use the .dt as mentioned

    I'm using table.on('preXhr'... which has the Datatable API so the .dt namespace is not needed but you can use it if you. Use the .dt namespace in cases where the event handler is created before Datatables initialization like the example in the docs:

    $('#example')
        .on('preXhr.dt', function (e, settings, data) {
            data.sessionId = $('#sessionId').val();
        })
        .DataTable({
            ajax: 'data.json'
        });
    

    I didn't want the preXhr executing with the initial ajax request.

    Is there an object-based way to access my columns

    $("td:eq(5)", row) is a jQuery selector which don't wrk with Javascript objects. Using a class name might be a good option. Use columns.className to define the class. Add this to your columns config with the columns.data definition. Here is an example using columnDefs:
    https://live.datatables.net/caporiva/3/edit

    I changed the index to the Office column. Relevant code:

      columnDefs: [
        {
          targets: 2,
          className: 'my-class'
        }
      ],
    
        rowCallback: function (row, data, index) {
            if (data[2] == "London") {
                console.log("London")
                $("td.my-class", row).addClass("status-up");
            }
    

    Kevin

  • zthomaszthomas Posts: 10Questions: 2Answers: 0
    edited June 26

    doesn't that still make fragile code? I would hope to be able to do something like

    columnDefs: [
      {
        targets: 'office',
        className: 'my-class'
      }
    ],
    

    to avoid issues if columns get reordered like you mentioned originally here.

  • kthorngrenkthorngren Posts: 21,342Questions: 26Answers: 4,954
    Answer ✓

    You could do that but the class office will need to be defined in the HTML table, like this:
    https://live.datatables.net/caporiva/4/edit

    However if you define the class in the HTML table you might just want to use that, for example: $("td.office", row).addClass("status-up");.

    to avoid issues if columns get reordered like you mentioned

    Since you changed to using objects I assume you are using columns not columnDefs to define the columns.data. I did suggest it would be better to define the columns.className in your columns.data definition. So if you rearrange the column order in your Datatable config then both will move at the same time. Like this:
    https://live.datatables.net/tufizeki/1/edit

    Kevin

  • zthomaszthomas Posts: 10Questions: 2Answers: 0

    Your last example made it clear, somehow I read past that explanation in the earlier post. Thank you for all the help, I think I'm good now!

  • kthorngrenkthorngren Posts: 21,342Questions: 26Answers: 4,954

    somehow I read past that explanation in the earlier post

    We all miss something when reading posts from others :smile:

    Glad its clear now.

    Kevin

Sign In or Register to comment.