how can I trigger jquery datatables fnServerData t

2019-02-02 13:39发布

问题:

I'm using the datatables plugin with server-side data and am updating the table using AJAX.

My dataTables setup looks like this:

tblOrders = parameters.table.dataTable( {
    "sDom": '<"S"f>t<"E"lp>',
    "sAjaxSource": "../file.cfc",
    "bServerSide": true,
    "sPaginationType": "full_numbers",  
    "bPaginate": true,
    "bRetrieve": true,
    "bLengthChange": false,         
    "bAutoWidth": false,
    "aaSorting": [[ 10, "desc" ]],      
    "aoColumns": [                      
        ... columns 
                  ],
    "fnInitComplete": function(oSettings, json) {
        // trying to listen for updates
        $(window).on('repaint_orders', function(){
            $('.tbl_orders').fnServerData( sSource, aoData, fnCallback, oSettings );
            });
        },
    "fnServerData": function ( sSource, aoData, fnCallback, oSettings ) {
        var page = $(oSettings.nTable).closest('div:jqmData(wrapper="true")')
        aoData.push(
            { "name": "returnformat", "value": "plain"},
            { "name": "s_status", "value": page.find('input[name="s_status"]').val() },
            { "name": "s_bestellnr", "value": page.find('input[name="s_bestellnr"]').val() },
            { "name": "form_submitted", "value": "dynaTable" }
            );
        $.ajax({ "dataType": 'json', "type": "POST", "url": sSource, "data": aoData , "success": fnCallback });
        }

I have some custom fields for filtering the data server-side, which i'm pushing along with the AJAX request. The problem is, I don't know how to trigger a JSON request from outside of the table. If the user types into the filter, fnServerData fires and updates the table. However, if the user picks a control outside of the table, I have no idea how to trigger the fnServerData function.

Right now I'm trying with a custom event I'm firing and listening to in fnInitComplete. While I can detect the user picking a custom filtering criteria, I'm missing all parameters needed for fnServerData to trigger correctly.

Question:
Is there a way to trigger fnServerData from a button outside of the actual dataTables table?

I guess I could try to add a space to the filter, but this is not really an option.

Thanks for input!

Question

回答1:

I found this script some time ago (so I don't remember where it came from :( and who to credit for it :'( ) but here :

$.fn.dataTableExt.oApi.fnReloadAjax = function (oSettings, sNewSource, fnCallback, bStandingRedraw) {
    if (typeof sNewSource != 'undefined' && sNewSource != null) {
        oSettings.sAjaxSource = sNewSource;
    }
    this.oApi._fnProcessingDisplay(oSettings, true);
    var that = this;
    var iStart = oSettings._iDisplayStart;
    var aData = [];

    this.oApi._fnServerParams(oSettings, aData);

    oSettings.fnServerData(oSettings.sAjaxSource, aData, function (json) {
        /* Clear the old information from the table */
        that.oApi._fnClearTable(oSettings);

        /* Got the data - add it to the table */
        var aData = (oSettings.sAjaxDataProp !== "") ?
            that.oApi._fnGetObjectDataFn(oSettings.sAjaxDataProp)(json) : json;

        for (var i = 0; i < aData.length; i++) {
            that.oApi._fnAddData(oSettings, aData[i]);
        }

        oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
        that.fnDraw();

        if (typeof bStandingRedraw != 'undefined' && bStandingRedraw === true) {
            oSettings._iDisplayStart = iStart;
            that.fnDraw(false);
        }

        that.oApi._fnProcessingDisplay(oSettings, false);

        /* Callback user function - for event handlers etc */
        if (typeof fnCallback == 'function' && fnCallback != null) {
            fnCallback(oSettings);
        }
    }, oSettings);
}

Add that BEFORE you call the datatable initialization function. then you can just call the reload like this:

$("#userFilter").on("change", function () {
        oTable.fnReloadAjax(); // In your case this would be 'tblOrders.fnReloadAjax();'
    });

userFilter is an ID for a dropdown, so when it changes, it reloads the data for the table. I just added this as an example but you can trigger it on any event.



回答2:

From a discussion here, Allan (the DataTables guy) suggests that simply calling fnDraw will yield the results you're looking for. This is the method I use for reloading server-side stuff (via fnServerData, which is important), and it's worked so far.

$("#userFilter").on("change", function() {
    oTable.fnDraw();  // In your case this would be 'tblOrders.fnDraw();'
});


回答3:

All the solutions mentioned before have some problem (for example, the additional user http paramaters are not posted or are stale). So I came up with following solution that works well.

Extension function (My params are array of key value pairs)

<pre>
$.fn.dataTableExt.oApi.fnReloadAjax = function (oSettings, sNewSource, myParams ) {
if ( oSettings.oFeatures.bServerSide ) {
    oSettings.aoServerParams = [];
    oSettings.aoServerParams.push({"sName": "user",
        "fn": function (aoData) {
            for (var i=0;i<myParams.length;i++){
            aoData.push( {"name" : myParams[i][0], "value" : myParams[i][1]});
         }
     }});
     this.fnClearTable(oSettings);
     this.fnDraw();
     return;
    }
};
</pre>

Example usage to put in you refresh event listener.

<pre>
oTable.fnReloadAjax(oTable.oSettings, supplier, val);
</pre>

Just one thing to pay attention to. Do not redraw table, once it's created, beacuse it's time consuming. Therefore, be sure to draw it only the first time. Otherwise, reload it

<pre>
var oTable;
if (oTable == null) {
    oTable = $(".items").dataTable(/* your inti stuff here */); {
}else{
    oTable.fnReloadAjax(oTable.oSettings, supplier, val);
}
</pre>


回答4:

In the initialization use:

"fnServerData": function ( sSource, aoData, fnCallback ) {
                    //* Add some extra data to the sender *
                    newData = aoData;
                    newData.push({ "name": "key", "value": $('#value').val() });

                    $.getJSON( sSource, newData, function (json) {
                        //* Do whatever additional processing you want on the callback, then tell DataTables *
                        fnCallback(json);
                    } );
                },

And then just use:

$("#table_id").dataTable().fnDraw();

The important thing in the fnServerData is:

    newData = aoData;
    newData.push({ "name": "key", "value": $('#value').val() });

if you push directly to aoData, the change is permanent the first time and when you draw the table again the fnDraw don't work the way you want. So, use a copy of aoData to push data to the ajax.



回答5:

I know this is late to the game, but fnDraw (from this answer above - which should be the accepted answer), is deprecated as of v1.10

The new method is:

this.api( true ).draw( true );

Which, BTW, has a comment that reads:

// Note that this isn't an exact match to the old call to _fnDraw - it takes
// into account the new data, but can hold position.


回答6:

Similar to Mitja Gustin answer. Changed a loop, added sNewSource.

$.fn.dataTableExt.oApi.fnReloadAjax = function (oSettings, sNewSource, myParams ) {
    if(oSettings.oFeatures.bServerSide) {
        if ( typeof sNewSource != 'undefined' && sNewSource != null ) {
            oSettings.sAjaxSource = sNewSource;
        }
        oSettings.aoServerParams = [];
        oSettings.aoServerParams.push({"sName": "user",
            "fn": function (aoData) {
                for(var index in myParams) {
                    aoData.push( { "name" : index, "value" : myParams[index] });
                }
            }
        });
        this.fnClearTable(oSettings);
        return;
    }
};

var myArray = {
    "key1": "value1",
    "key2": "value2"
};

var oTable = $("#myTable").dataTable();
oTable.fnReloadAjax(oTable.oSettings, myArray);


回答7:

For reload of the data, simply you need to select the DataTable using jquery selector with DataTable() function and call _fnAjaxUpdate function.

Here is example:

$('#exampleDataTable').DataTable()._fnAjaxUpdate();