Bootstrap 5 tooltip disappears in child rows after ajax reload of DataTable

Bootstrap 5 tooltip disappears in child rows after ajax reload of DataTable

Brecht2727Brecht2727 Posts: 28Questions: 4Answers: 0
edited September 2023 in Free community support

Hi all,

the tooltip is shown behind the drawCallback function in the child rows, but after the automatic reload it is gone again

  new DataTable('#myTable', {
    drawCallback: function () {

      let tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]');
      let tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl, {
        boundary: document.body,
        container: 'body',
        trigger: 'hover'
      }));

      tooltipList.forEach((tooltip) => { $('.tooltip').hide(); });

    },
    dom: '<"top"<"left-col"B><"center-col"r><"right-col"f>>t<"bottom"lip>',
    processing: true,
    serverSide: true,
    serverMethod: 'post',
    ajax: {
      url: 'ajax/get-table-data.php',
      data: function(data){
        data.searchByTimeslot = localStorage.getItem("kiwanis_search_timeslot");
      }
    },
    rowId: 'id',
    columns: [
      { data: 'id' },
      { className: 'dt-control',
        orderable: false,
        data: null,
        defaultContent: ''
      },        
      { data: 'fullname' },
      { data: 'email' },
      { data: 'phone' },
      { data: 'kids' },
      { data: 'adults' },
      { data: 'drinks' },
      { data: 'deserts' },
      { data: 'price', render: DataTable.render.number( null, null, 2, null, ' €' ) }, //DataTable.render.number(thousands, decimal, precision, prefix, postfix)
      { data: 'timeslot' },
      { data: 'created' },
      { 
        targets: [12],
        orderable: false,
        class: 'text-center',
        render: function ( data, type, row ) {

          if(row.remarks) {
            var a = row.remarks2;
          } else {
            var a = '';
          }
          
          a += row.remarks3;

          return a;

        }         
      },
      { data: 'total_amount_per_row' }
    ],
    columnDefs: [
      { 
        targets: [0,13],
        visible: false
      },
      { 
        targets: [4,5,6,7,8,9,10,11],
        class: 'text-center',
        orderable: false
      },
      { 
        targets: [0,1,2,3],
        orderable: false
      }
    ],    
    order: [[0, "desc"]],
    lengthMenu: [
      5, 10, 15, 20, 25
    ]
  });

  function onClickEventListener() {
    var tr = $(this).closest('tr');
    var row = $('#myTable').DataTable().row(tr);  

    if (row.child.isShown()) {

      // This row is already open - close it
      row.child.hide();
      tr.removeClass('shown'); 
   
    } else {

      // Open this row
      row.child(format(row.data())).show();
      tr.addClass('shown');
      
      let tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]');
      let tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl, {
        boundary: document.body,
        container: 'body',
        trigger: 'hover'
      }));
      
    }

    let currentRowID = "#" + ($(this).closest('tr').attr('id'));

    if ($.inArray(currentRowID, rowIds) !== -1) {

      //Row is closed, remove row ID from rowIDs array
      var index = rowIds.indexOf(currentRowID);
      if (index !== -1) rowIds.splice(index, 1);
      rowIds.filter(function (val) {
          return val;
      }); 
      
    } else {

      //Row is opened, add row ID to rowIDs array
      rowIds.push(currentRowID);
      
    }
  }    

  // Add event listener for opening and closing the row
  $('#myTable tbody').on('click', 'td.dt-control', onClickEventListener);

  //set interval to update datatable
  setInterval(function () {
    $('#myTable').DataTable().ajax.reload(function () {
      //Iterate through all the open rows and open them again   <--Value is set in the onClickEventListener function
      $('#myTable').DataTable().rows(rowIds).every(function (row, index, array) {
        $('#myTable').DataTable().row(row).child(format(this.data())).show();
        this.nodes().to$().addClass('shown');
      });
      //Set to false if you don't want the paging to reset after ajax load,otherwise true
    }, false);
  }, 10000);

This question has an accepted answers - jump to answer

Answers

  • kthorngrenkthorngren Posts: 21,299Questions: 26Answers: 4,944
    Answer ✓

    I'm not sure of the order of operations but I suspect that drawCallback is called before the loop in line 134. You could determine the order with console.log statements or stepping through the code with the debugger. If this is the case then you may need to call draw() with "page" as the parameter, to redraw the page without searching and sorting, after the loop on line 138.

    If you still need help please build a simple test case showing the issue so we can help debug.
    https://datatables.net/manual/tech-notes/10#How-to-provide-a-test-case

    You can get Ajax or server side loaded data templates from here:
    https://datatables.net/manual/tech-notes/9

    Kevin

  • Brecht2727Brecht2727 Posts: 28Questions: 4Answers: 0

    Hi Kevin,

    Thanks for helping again ;-)
    I had to initialize the bootstrap tooltip code again in the reload callback.

    I updated my code for the reload interval to this:

      setInterval(function () {
        $('#myTable').DataTable().ajax.reload(function () {
          //Iterate through all the open rows and open them again   <--Value is set in the onClickEventListener function
          $('#myTable').DataTable().rows(rowIds).every(function (row, index, array) {
            $('#myTable').DataTable().row(row).child(format(this.data())).show();
            this.nodes().to$().addClass('shown');
          });
          
          const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]');
          const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl, {
            boundary: document.body,
            container: 'body',
            trigger: 'hover'
          }));
          
          //Set to false if you don't want the paging to reset after ajax load,otherwise true
        }, false);
      }, 10000);
    
Sign In or Register to comment.