1

I've got a jQuery DataTable object that holds log information - how many log messages of type Exception, information etc. an application has logged during a certain date range. I want to update those values as log messages are sent to the underlying DB. I'm currently using javascript to find a cell in HTML table based on an AppId and updating the innerHTML with the new log total. However, since not all applications may be visible e.g. if there are 15 but the table is only set to show 10 entries, I want to update the values in the DataTable object so the values are correct if/when the applications are included in the table.

I've tried changing the values in the DataTable by doing something like this

var rows = table.rows().data();
var arr = data.aaData;
for (var i = 0; i < arr.length; i++) {
        for (var r = 0; r < rows.length; r++) {
            if (arr[i].ApplicationId == rows[r].AppId) {
                if (arr[i].Debug != 0 || arr[i].Information != 0 || arr[i].Message != 0 || arr[i].Warning != 0 || arr[i].Exception != 0) {
                    //New Exception Count
                    if (arr[i].Exception !== 0) {
                        rows[r].Exception = arr[i].Exception;
                        flash(rows[r].AppId, 'Exception');
                    }
                    //New Warning Count
                    if (arr[i].Warning !== 0) {
                        rows[r].Warning = arr[i].Warning;
                        flash(rows[r].AppId, 'Warning');
                    }
                    //New Message Count
                    if (arr[i].Message !== 0) {
                        rows[r].Message = arr[i].Message;
                        flash(rows[r].AppId, 'Message');
                    }
                    //New Information Count
                    if (arr[i].Information !== 0) {
                        rows[r].Information = arr[i].Information;
                        flash(rows[r].AppId, 'Information');
                    }
                    //New Debug Count
                    if (arr[i].Debug !== 0) {
                        rows[r].Debug = arr[i].Debug;
                        flash(rows[r].AppId, 'Debug');
                    }
                }
            }
        }
    }
    table.draw();

Where data.aaData is JSON format data returned from a controller method. Logging rows to the console I can see that values are updated in the DataTable object, but these new values aren't rendered to the HTML table during the table.draw() call.

So does anyone have a standard way of making changes to values in a DataTable? I've tried using table.cell(r, 5).data(someNewValue); for example but this seems to produce some unreliable results.

sam.gregory91
  • 83
  • 1
  • 1
  • 9

1 Answers1

2

Strange your attempt with table.cell(r, 5).data(someNewValue) not is working. Anyway, you can go the other way around, of course. The keyword here is to use invalidate(). If we have a table :

<table id="example"></table>

and some data in JSON format

var data = [
    { "name" : "david", "lastname" : "konrad" }
];

and initialise the dataTable like this

var table = $('#example').DataTable({ 
    data : data,
    columns : [
        { data : "name", title :'name' },
        { data : "lastname", title : 'last name' }
    ]
})

then you can change the content of the dataTable by updating the data JSON this way :

data[0].name = 'sam';
data[0].lastname = 'gregory';

table.row(0).invalidate().draw();

for a specific row, or just

table.rows().invalidate().draw();

for the entire dataset.

demo -> http://jsfiddle.net/vvzvxarf/


Update. You can do the exact same as above with an AJAX data source :

$('#example').DataTable( {
  ajax: {
    url: "someUrl",
    dataSrc: function(json) {
       //manipulate the data JSON as you wish
       //in this case, you dont need to invalidate() or draw()
       //...
       return json.data;
    }
})

Update II. Manipulating AJAX data after table is rendered. Simply "copy" the response JSON to a variable you can manipulate later on. A variable is simply just a reference. A small example :

var data;
var table = $("#example").DataTable({
    ajax : {
        url : 'data.json',
        dataSrc : function(json) {
            data = json.data;
            return json.data; 
        }
    },
    columns : [
        { data : 'first_name' }
    ]
})

setTimeout(function() {
    data[0].first_name = 'sam';
    table.row(0).invalidate().draw();
}, 100)

The result is exactly the same as my very first example.

davidkonrad
  • 83,997
  • 17
  • 205
  • 265
  • The only issue with that is that I'm using an ajax call to a controller method to populate the table, so can't update the JSON data. I've tried updating the data in the `table.rows().data()` object and then calling `table.row(row).invalidate().draw();` but that doesn't seem to work either – sam.gregory91 Sep 21 '15 at 08:12
  • @sam.gregory91, you can update / manipulate the JSON if you are using an AJAX data source too. Define `dataSrc` as a function where the param is the JSON response from your AJAX call, you then can manipulate before it is rendered by dataTable. See update. – davidkonrad Sep 21 '15 at 09:35
  • the only thing is I need to manipulate and update this _after_ the table is rendered – sam.gregory91 Sep 21 '15 at 09:47
  • @sam.gregory91, yes - and ..? See update II. I think you overcomplicate the issue. There is absolutely no diference. Just save the response in a variable, this variable is in fact just a reference to the original JSON used by dataTables. When you later on work on this reference, you are working on dataTables dataset too. The timeout in update II is just to make an delay, otherwise the code will be executed before dataTables has finished its business. In your case it does not matter because you have an entire update function you are clalling on a certain point later on. – davidkonrad Sep 21 '15 at 10:28
  • you're right I was overcomplicating the issue. Being a newbie to javascript I was making mistakes with variable scope. I can access and manipulate the data now, but after adding `dataSrc` to the ajax call the DataTable object returned from `$('#myTable').DataTable()` is different, i,e. all the functions have changed. – sam.gregory91 Sep 21 '15 at 12:52
  • @sam.gregory91 - You can use your old `dataTable()` initialization and still access the new API as `table.DataTable().row(0).invalidate().draw();` instead. I am little surprised - you are mentioning `table.rows().data()` yourself in the question. Next time, please include all relevant parts of the script in your question. I guess you would have received an usefull answer much faster, if you had shown how you actually are using dataTables too :) But great it is working now. Cheers. – davidkonrad Sep 21 '15 at 13:04
  • I could call `table.rows().data()` before but after adding the `dataSrc` option to the ajax call the DataTable object returned changed to having function with prefix `fn` or `_fn` in front of them all. Yeah it's not a problem just thought you'd be interested to know – sam.gregory91 Sep 21 '15 at 13:13
  • @sam.gregory91 - yes, if you initialise with `dataTable()` you get the oldschool jQuery object with `fnXXX` functions. If you use the `DataTable()` initialisation you get the API object. But you can combine those by adding `table.dataTable().fnOldFunction` and / or `table.DataTable().newAPIfunction()`. – davidkonrad Sep 21 '15 at 13:19
  • @sam.gregory91, the confusion was somehow my fault since I in the example with dataSrc accidently used dataTable(). Have corrected this now. See this BTW -> http://stackoverflow.com/q/25207147/1407478 – davidkonrad Sep 21 '15 at 13:22
  • ah right that makes sense, in my rearranging I must've taken out a `.DataTable()` call and my original initialisation returned the table after a `.dataTable()` call. Thanks! – sam.gregory91 Sep 21 '15 at 14:03