1

The following code is in my ColumnDefs part of the DataTables table's initialization. In the FireBug, I am noticing that the call to my ColdFusion CFC is being made twice per column--which is inefficient. Please note the following code is based on: Data table column rendering with ajax response .

Update 1 Here is most of the code--note, not all columns and their Rendering is present in this code. https://docs.google.com/document/d/1t9vERsngpporbrU-FbE9esjt-KHL0qjLK076qkldGZ8/edit?usp=sharing

{
    "targets": 11, /* Date Created */
     "render": function (data, type, row, meta) { 
      var currentCell = $("#table_main_admin").DataTable().cells({"row":meta.row, "column":meta.col}).nodes(0);
           $.ajax({ 
            url: 'date_conversions.cfc',  
            dataType: 'json',
            data: {method: 'format_date_via_coldfusion', date_input: data}, 
            }).done(function (success) { $(currentCell).html(success.mydate); });
            return null;
          }  
}
IrfanClemson
  • 1,699
  • 6
  • 33
  • 52

1 Answers1

4

Why are duplicate calls being made?

Because the render callback is called for all request types - that is display, filter, sort and type. In your case it is called initially twice per row

  • one time for display, i.e retrieving the data
  • a second time for filter since you have a order on the columns, at least the default order

Obviously anything than the first AJAX request is redundant. Normally you can avoid consecutively requests simply by testing on the type, but you have a setup with AJAX where values should be injected delayed.

The solution you have above by inserting success.mydate via DOM is actually the worse part: It will never work since any value is forgotten on next draw. And you cannot simply return success.mydate either (classic async problem)

I will suggest you maintain a list of processed (ajaxed) values in meta.settings.aoColumns[] (so you can have multiple columns with that setup in the same table).

  • As mentioned in the first answer, check if type is of kind display; this is the very first request and the only one you want / need to process.

  • Then check if you already have processed the column for the row, if not do the ajax stuff and in done() update both the processed value and the cell through the API!

  • Meanwhile return a dummy string or perhaps the initial value of data.

  • In all other cases, return the processed value from meta.settings.aoColumns[]

I cannot replicate your setup above accurately, but here is the scheme :

render: function(data, type, row, meta) {
  if (!meta.settings.aoColumns[meta.col]._processed) {
    meta.settings.aoColumns[meta.col]._processed = []
  }  
  var processed = meta.settings.aoColumns[meta.col]._processed 
  if (type == 'display') {
    if (!processed[meta.row]) {
      processed[meta.row] = 'waiting ...' + meta.row

      $.ajax({
        url : 'https://api.myjson.com/bins/avxod'
      }).done(function(success) {
        var fakeVal = 'Ok, done '+meta.row //success.mydate
        processed[meta.row] = fakeVal

        //update through the API 
        $('#example')
          .DataTable()
          .cell({ row: meta.row, column: meta.col })
          .data( fakeVal )
          .invalidate()

      })
      return processed[meta.row]
    } else {
      return processed[meta.row]
    }
  } else {
    return processed[meta.row]
  }   
}

I believe it is pretty fail proof. Here is a demo -> http://jsfiddle.net/0bsbw6gt/

davidkonrad
  • 83,997
  • 17
  • 205
  • 265
  • I think you may be onto something but now the column doesn't even display any data--and it should. thx – IrfanClemson Jan 04 '18 at 17:20
  • Still no luck. Some of my 'data' variables can be empty and they generate ColdFusion error trying to convert to date but still [ if (data.length > 5 && type == 'display') {] causes multiple calls. Thanks. – IrfanClemson Jan 04 '18 at 17:40
  • Thanks. Kind of toying in the dark here. – IrfanClemson Jan 04 '18 at 17:54
  • @Meengla, OK, see the update. Hope you can adapt it. You can delete comments. – davidkonrad Jan 04 '18 at 18:56
  • Thanks. Not sure I can adopt it in my code; yours is a long code. Basically, I have the ColumnnDefs and under that have 3 Date columns using Ajax. Thanks much – IrfanClemson Jan 04 '18 at 19:00
  • 1
    "*...have 3 Date columns using Ajax*" thats why the processed status need to be stored in the settings column object itself (alternatively in a external dictionary of arrays) I do not think it is particular "long"; you **will** need to return values in any case, also while ajaxing; you **will** need to have a "clever" way to keep track of the processing status and do a delayed insertion of the ajaxed values to DataTables internals the right way. – davidkonrad Jan 04 '18 at 19:13
  • Anyway, first time I have seen this setup :) You could reduce the complexity a little bit if you skip the render callbacks totally and do all the ajaxing in loops after the DataTable is initialised, but you will still need to update the internals and invalidate. – davidkonrad Jan 04 '18 at 19:14
  • Hi, please see an Update to the question, which has an Update 1 , linking to the code being used. Thanks! – IrfanClemson Jan 04 '18 at 19:21
  • @Meengla, this was worse, for I can see you are using serverside processing, this means you not get anything out of "caching" the results anyway (or it should be done quite different by unique id's) **any** action will force new load and rendering. 1) Is it impossible to include the dates in the serverside data? 2) If not, do the ajax stuff in the drawCallback callback, and in that maintain dictionaries/lookup-lists for already ajaxed dates. serverSide processing means *anything* goes via backend, and on top of that you have consecutively ajax calls, really a heavy cocktail :) – davidkonrad Jan 05 '18 at 10:58
  • Hi, I have Accepted your Answer; indeed, no more multiple calls. However, var fakeVal = success.mydate is not showing up the date--getting stuck in 'waiting'; if put in just success then the whole object shows with the correct date as { "mydate": "1/3/2018 2:22 PM"} – IrfanClemson Jan 05 '18 at 19:06
  • Never mind; had to specify dataType: 'json', . Thanks!! – IrfanClemson Jan 05 '18 at 19:10
  • @davidonrad Hi, your solution works except during paginations, sometimes the dates from the previous page are carried. I think that's because of the way the code is looking to see if already rendered a cell or not. Any idea? Thanks. – IrfanClemson Jan 12 '18 at 13:58
  • ***Never mind. I ended up formatting the dates server side during the query itself--not need for any Ajax calls. While the Accepted Answer got me started it has the flaw during pagination--as I commented above. Please be aware.*** – IrfanClemson Jan 12 '18 at 19:48