1

I have the following DataTable which calls status_icons() function for replacing 0 & 1 values with icons.

At first results page (on initComplete) I call status_icons() for the replacement and then I make a trigger out of DataTables scope in order to have my function re-executed for next paginated results due to DataTable DOM reconstruction behavor for each pagination.

The error I get is that re-adds the status icons over the current ones when you you click on the "Previous" button on any pagination or the numbered pagination boxes.

My function for replacing values with icons

function status_icons() {

    $('table tr').each(function() {
        if ($(this).find('td').eq(0).text() == '1') {
            $(this).find('td').eq(0).replaceWith('<i class="fa fa-3 fa-check-circle-o datatable-paid-1"></i>');
        } else {
            $(this).find('td').eq(0).replaceWith('<i class="fa fa-3 fa-exclamation-circle datatable-paid-0"></i>');
        }
    });
}

DataTable construction - on initComplete calls the function for the first and second page results

setTimeout(function() {
  $('#invoices-table').DataTable({
    responsive: true,
    columnDefs: [{ orderable: false, targets: [-1, -2, -3] }],
    dom: 'Bfrtip',  
    initComplete: function() {
      status_icons() // it executes my function for the first page of results
      var api = this.api();
      // some irrelevant code that uses api and does not cause my issue
      // ...

    }
  });
}, 1000);

jQuery event for executing my function each time a .paginate_button is clicked due to DataTable reconstruction

$(document).on('click','.paginate_button', function() {
  if( !$(this).hasClass("disabled") ){
    status_icons(); // it executes for the rest paginations
  }
});

https://codepen.io/anon/pen/Wjqbbd

2 Answers2

1

In general it is a really bad thing to delegate events to the document object. Furthermore, dataTables steals the click event totally, preventing you from adding additionally click event handlers to .paginate_buttons. A working event handler on a .paginate_button would be

$('body').on('mousedown','.paginate_button', function() {
  ...
})

However, your approach is somehow exaggerated or "wrong" in the context of what you want to achieve. dataTables have a columns.render callback to deal with exact those issues. Simply add this to your columDefs section :

columnDefs: [
  { orderable: false, targets: [-1, -2, -3] },
  { targets : 0, 
    render: function(data, type) {
      if (type == 'display') {
        return data == '1' 
          ? '<i class="fa fa-3 fa-check-circle-o datatable-paid-1"></i>'
          : '<i class="fa fa-3 fa-exclamation-circle datatable-paid-0"></i>'
      } else {
        return data
      }
    }
  }
],

And you are good. It solves both problems: The one with lack of action on click, you dont have to worry on page changes at all - and the one with replicated font awesome icons inserted over and over.

It simply works by returning the correct <i> font awesome markup when dataTables want to display content for the column.

Have ported your code to a jsfiddle -> http://jsfiddle.net/2tzp19se/

davidkonrad
  • 83,997
  • 17
  • 205
  • 265
  • Good answer! +1... But is there any reason for the `setTimeout({...},0);` in the Fiddle? – Louys Patrice Bessette May 29 '17 at 20:43
  • 1
    hey @LouysPatriceBessette, no - just copy paste from OP's codepen. I just changed 1000ms to 0ms (because I really cannot see the reason for a timeout) but like to keep the code recognizeable for OP, so kept the original structure. – davidkonrad May 29 '17 at 20:48
  • The only part I do not get in your answer is `targets: [-1, -2, -3]`. Can you explain? I'm sure, OP doesn't know either ;) Haaa... Forget it, I found. Those negative numbers are column indexes, counted from the right, to disable ordering. – Louys Patrice Bessette May 29 '17 at 20:55
  • @LouysPatriceBessette, yes! This is also part of OP's original code. Have just changed the event handler (as an example of the first part in the answer) then commented `status_icons()` out and added a new `columnDefs` section targeting the first column. – davidkonrad May 29 '17 at 21:04
  • Undoubtly your answer/solution gives extra value to the problem, great! Now `targets: 0` is for the first column, how it could be possible to put in this parameter an extra statement that pending on ` data == "1"` can affect also column 3, let's say change its class to disabled. It seems not to give space for multiple statements that goes directly to other columns simultaneously –  May 31 '17 at 07:11
  • I transfered my question comment to new post https://stackoverflow.com/questions/44282088/datatables-data-replacement-to-multiple-columns-based-on-ones-value –  May 31 '17 at 10:26
0

Just use .html() instead of .replaceWith().

.replaceWith() does not only replace the td content...
But replaces the td itself with the passed argument (string or object).

Updated CodePen

Louys Patrice Bessette
  • 33,375
  • 6
  • 36
  • 64
  • Louys thanks for your response! Your solution fixes previous issue but causes a new one. When you go in the last results (Page 4 with 1's in status column) and then you go back (Page 3) then all the 1s lose their replacement font icon (green check) and render only the exclamation mark (the one which replaces the 0s) –  May 30 '17 at 13:12
  • 1
    I fixed it in the CodePen... I simply added a condition for the `else`. --- But to be honnest, the other answer is better than mine. ;) – Louys Patrice Bessette May 30 '17 at 15:23
  • Well it might.. but to be also honest you answered directly to what I asked so that makes your answer strictly directed and not lesser + it worked as well :) –  May 31 '17 at 07:15