Need help Row details dont work properly

Need help Row details dont work properly

laurent09laurent09 Posts: 18Questions: 0Answers: 0

hi

to start sorry if my english is not very good I'm french.

I do not know how to explain that.

I put in my datatable row details ( https://datatables.net/examples/server_side/row_details.html ), but it does not work properly.

in the beginning everything works, on all the lines of my table.
when I change the category (ex: PUBG) it works, I can open row detail for my 3 lines, but when I put back without category (all games), only the first 3 lines work, I can not open row detail for others.

I dont understand why it does not work after.

someone can help me ?

my website : http://ckdn.esy.es/

table page html:

                  <table id="product_data" class="">
                     <thead>
                        <tr>
                            <th  style="width: 28px;" ></th>
                             <th><i class="far fa-calendar-alt"></i></th>
                             <th><i class="far fa-user"></i></th>
                           <th><i class="far fa-gamepad"></i>
                              <select name="category" id="category" class="form-control">
                                   <option value="">Touts les Jeux</option>
                                   {$envoie} <!-- reçoit la boucle php  -->
                              </select>
                           </th>
                            <th>Age</th>
                        </tr>
                     </thead>
                  </table>

script page html

         <script type="text/javascript" language="javascript" >
  $(document).ready(function (){

   load_data();

   function load_data(is_category)
   {
    var dataTable = $('#product_data').DataTable({
     "processing":true,
     "serverSide":true,
     "order":[],
     "ajax":{
      url:"includes/fetch.php",
      type:"POST",
      data:{is_category:is_category}
     },
     "columns": [
              {
                  "className":      'details-control',
                  "orderable":      false,
                  "data":           null,
                  "defaultContent": ''
              },
              { "data": 1},
              { "data": 2},
              { "data": 3,
                "orderable":false,},
              { "data": 4 }
          ],
     "language": {
       "processing": "<div id='loader'></div>"
    }
    });

  // affiche plus de détaille annonce 
  function format ( d ) {
      if ( d[5] == '') {
        $online = '<div class="steamWidget no-steam">'+
                  'Statut Steam: <p>Steam Non renseigné</p><br><br>'+
                  'Description Prochainement</div>';

      } else {

        if ( d[5] == 'online') {
              $online = '<div class="steamWidget online">'+
                        'Statut Steam:<p>'+d[5]+'</p><br><br>'+
                        'Description Prochainement</div>';
            }
            else  {
                $online = '<div class="steamWidget offline">'+
                          'Statut Steam:<p>'+d[5]+'</p><br><br>'+
                          'Description Prochainement</div>'; 
            }

      }
      return $online;
  }

        // affiche plus de détaille annonce suite
      $(document).on('click', 'td.details-control', function () {
          var tr = $(this).closest('tr');
          var row = 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');
          }
      } );

   }
  // change la catégorie
   $(document).on('change', '#category', function(){
    var category = $(this).val();
    $('#product_data').DataTable().destroy();
    if(category != '')
    {
     load_data(category);
    }
    else
    {
     load_data();
    }
   });
  </script>

And my fetch page:

      require_once('../includes/config.php');
          $connect = new mysqli($CONF['host'], $CONF['user'], $CONF['pass'], $CONF['name']);
          if ($connect->connect_errno) {
              echo "Failed to connect to MySQL: (" . $connect->connect_errno . ") " . $connect->connect_error;
          };

        $column = array("","date_add", "username", "category_g_name", "born");
        $query = "
         SELECT * FROM users U
         INNER JOIN users_category UC ON (U.idu = UC.id_users)
         INNER JOIN category_games C ON (UC.id_category = C.id)  
        ";
        $query .= " WHERE";
        $query .= " UC.recherche = 1 AND";
        if(isset($_POST["is_category"]))
        {
         $query .= " id = '".$_POST["is_category"]."' AND ";
        }


        if(isset($_POST["search"]["value"]))
        {
         $query .= '(date_add LIKE "%'.$_POST["search"]["value"].'%" ';
         $query .= 'OR username LIKE "%'.$_POST["search"]["value"].'%" ';
         $query .= 'OR category_g_name LIKE "%'.$_POST["search"]["value"].'%" ';
         $query .= 'OR recherche LIKE "%'.$_POST["search"]["value"].'%" ';
         $query .= 'OR born LIKE "%'.$_POST["search"]["value"].'%") ';
        }

        if(isset($_POST["order"]))
        {
         $query .= 'ORDER BY '.$column[$_POST['order']['0']['column']].' '.$_POST['order']['0']['dir'].' ';
        }
        else
        {
         $query .= 'ORDER BY date_add DESC ';
        }

        $query1 = '';

        if($_POST["length"] != 1)
        {
         $query1 .= 'LIMIT ' . $_POST['start'] . ', ' . $_POST['length'];
        }


        $number_filter_row = mysqli_num_rows(mysqli_query($connect, $query));

        $result = mysqli_query($connect, $query . $query1);

        $data = array();



        while($row = mysqli_fetch_array($result))
        {   
            if (isset($row["steam"]))
                {
                    $steam = simplexml_load_file("https://steamcommunity.com/profiles/".$row["steam"]."?xml=1", 'SimpleXMLElement', LIBXML_NOCDATA);
                    $steamstatut = str_replace("<br />", " - ", $steam->onlineState);
                } else {
                    $steamstatut = '';
                }

            // calcule age user
            $ub = explode('-', $row["born"]) ;
            $age = date('Y') - $ub[0] ;
            if ( date('md') < $ub[1].$ub[2] ) $age-- ; 

            //calcul nbr de our de l'annonce
            $now = new DateTime("now");
            $dateBdd = new DateTime($row["date_add"]);
            //$date_add = $dateBdd1->diff($now)->format("%d jours, %h heurs and %i minutes");
            $date_add = $dateBdd->diff($now);
            $jours = $date_add->format("%d jrs");
            $heurs = $date_add->format("%h hrs");
            $minute = $date_add->format("%i min");
            if ($jours == 0 ) {  

                if ($heurs == 0 ) {
                    $afficher = $minute;
                }
                else {
                    $afficher = $heurs;
                }
            }  else {
                    $afficher = $jours;
            }

            $URL = $CONF['url'];
         $sub_array = array();
         $sub_array[] = '<th></th>';
         $sub_array[] = $afficher;
         $sub_array[] = $row["username"];
         $sub_array[] = $row["category_g_name"];
         $sub_array[] =  $age. 'ans';
          $sub_array[] = $steamstatut;
         $data[] = $sub_array;

        }

        function get_all_data($connect)
        {

         $query = "SELECT * FROM users_category";
         $result = mysqli_query($connect, $query);
         return mysqli_num_rows($result);
        }

        $output = array(
         "draw"    => intval($_POST["draw"]),
         "recordsTotal"  =>  get_all_data($connect),
         "recordsFiltered" => $number_filter_row,
         "data"    => $data
        );

        echo json_encode($output);

thank a lot

Replies

  • colincolin Posts: 15,144Questions: 1Answers: 2,586

    Hi @laurent09 ,

    I just tried this against your site, and child rows were always being opened - for all rows, not just the first three. I did the following steps

    1. click on the '+' on first row (two rows are created)
    2. click on the '+' on the last row of the first page (two rows also created)
    3. changed to second page, and again clicked on first and last row

    Can you give more information please on why you feel it isn't working, and what you expect it should be doing.

    Cheers,

    Colin

  • laurent09laurent09 Posts: 18Questions: 0Answers: 0

    ok I will try to explain. lol

    1- I refresh my page only 1 times and just now.
    2- I click on the '+' I open all the rows, it's ok everything works all the rows opens.
    3- I change the category I put another games.
    4- I click on the '+' I open all the rows, it's ok everything works all the rows opens.
    5 - I change the category I put the first (" touts les jeux ").
    6- I click on the '+' I try to open the first three lines is ok, but the next do not want to display the rows.

    I hope you understand me

    thanks

  • colincolin Posts: 15,144Questions: 1Answers: 2,586

    Can you be more specific, please. I tried changing the game, but none of the others seem to have any data. If you could say exactly what you press, that would help us to see the same things.

  • laurent09laurent09 Posts: 18Questions: 0Answers: 0

    selected the game "PLAYERUNKNOWN'S BATTLEGROUNDS", there are 4 lines, and the rows chill works correctly for the 4 lines.

    and after selected in the category games "ALL THE GAMES" in the top of the list games.
    there are now all the lines, as in the beginning, but only the first 3 lines work properly when we click on the '+'. the other lines do not work, like on my screen.

  • laurent09laurent09 Posts: 18Questions: 0Answers: 0

    I found something else, it's difficult to explain.

    1- I refresh my page (ctrl + f5)
    2- I click on '+' all the lines work correctly.

    3- I select the game 'ARMA 3'.
    4- I have 1 result, I click on '+' and I open my row child correctly.

    5- I change my game and select 'ALL THE GAMES' in the top
    6-I have all my results, I click on '+', and only one row child works.
              I can only open 1 row child as when I selected the game 'arma 3'.

    7- I refreshed my page (ctrl + f5)
    8- I select the game 'PLAYERUNKNOWN'S BATTLEGROUNDS'.
    9- I have 4 result, I click on '+' and I open my 4 row child correctly.

    10- I change my games and select 'TOUTS LES JEUX' in the top
    11- I have all my results, I click on '+', and only 4 row child works.
              I can only open 4 row child like when I have selected the PLAYERUNKNOWN'S BATTLEGROUNDS game.

    I think maybe the problem is my loaddata ();

     $(document).on('change', '#category', function(){
      var category = $(this).val();
      $('#product_data').DataTable().destroy();
      if(category != '')
      {
       load_data(category);
      }
      else
      {
       load_data();
      }
     });
    

    je ne sais pas pourquoi.

  • colincolin Posts: 15,144Questions: 1Answers: 2,586

    Hi @laurent09 ,

    We worked it out. The problem is because you're destroying the table, but leaving old event handlers lying around that will trigger when the table no longer exists. This was causing these errors in the console:

    jquery.dataTables.min.js:120 Uncaught TypeError: Cannot read property '_detailsShow' of undefined
        at r.<anonymous> (jquery.dataTables.min.js:120)
        at Function.isShown (jquery.dataTables.min.js:102)
        at HTMLTableCellElement.<anonymous> ((index):186)
        at HTMLDocument.dispatch (jquery.js:2)
        at HTMLDocument.y.handle (jquery.js:2)
    

    The solution: instead of using destroy() it would be better (in order) to refactor the code to either use ajax.reload(), or, clear() the table and the reload with rows.add(), or, use off() to remove the event handlers.

    There's also little point using serverSide since your tables are so small - that's only needed when you have thousands of records in a table.

    Hope that all makes sense,

    Cheers,

    Colin

  • laurent09laurent09 Posts: 18Questions: 0Answers: 0

    really really thank you for your help @colin

    a simple $('#product_data').DataTable().ajax.reload(); does not work ?

    I am really sorry I beginner.

  • kthorngrenkthorngren Posts: 20,309Questions: 26Answers: 4,770

    $('#product_data').DataTable().ajax.reload();

    This should reload your ajax data. Does it not work for you?

    Kevin

  • laurent09laurent09 Posts: 18Questions: 0Answers: 0

    no it does not work.

    when I change the category games I have an error.

    // change la catégorie
     $(document).on('change', '#category', function(){
      var category = $(this).val();
    
      $('#product_data').DataTable().ajax.reload();
    
      if(category != '')
      {
       load_data(category);
      }
      else
      {
       load_data();
      }
     });
    

    my siteweb
    http://ckdn.esy.es/

  • kthorngrenkthorngren Posts: 20,309Questions: 26Answers: 4,770

    You are getting this error:

    DataTables warning: table id=product_data - Cannot reinitialise DataTable. For more information about this error, please see http://datatables.net/tn/3

    Did you read the tech note in the link provided in the error?

    Your load_data() function is reinitializing the Datatable each time its called. This is causing the error. In your ajax you are passing a data parameter to the server for the desired data.

    The technote provides a couple options that might work for you.
    https://datatables.net/manual/tech-notes/3#retrieve

    The first is retrieve which should eliminate the error but I'm not sure if the ajax call will use the updated data option. You can try it to see. Along with this option you might need to use clear() if the table isn't cleared of the previous data.

    If retrieve doesn't work then you can try the destroy option to see if it will work.

    A better option maybe to use an external ajax call to get the data then use rows.add() to add the data to the table. Before that you will need to use clear() to clear the previous data. Something like this example:
    http://live.datatables.net/heweruva/6/edit

    In all cases above you won't want to use $('#product_data').DataTable().ajax.reload();

    Kevin

  • laurent09laurent09 Posts: 18Questions: 0Answers: 0

    yes I read the note.
    I already have my table which is destroyed when I change the category at the line 40.

    and then he calls my ajax with "load_data ();"
    it works well, just as I explained earlier in the comment there is a problem with the child rows.

    I am really sorry I am a beginner, I want to understand and learn.

                 $(document).ready(function (){
    
                    load_data();
    
                  function load_data(is_category)
                   {
                    var dataTable = $('#product_data').DataTable({
    
                      retrieve: true,
                     "processing":true,
                     "serverSide":true,
                     "order":[],
                     "ajax":{
                      url:"includes/fetch.php",
                      type:"POST",
                      data:{is_category:is_category}
                     },
                     "columns": [
                              {
                                  "className":      'details-control',
                                  "orderable":      false,
                                  "data":           null,
                                  "defaultContent": ''
                              },
                              { "data": 1},
                              { "data": 2},
                              { "data": 3,
                                "orderable":false,},
                              { "data": 4 }
                          ],
                     "language": {
                       "processing": "<div id='loader'></div>"
                    }
                    });
    
    
                     // change la catégorie
                         $(document).on('change', '#category', function(){
                          var category = $(this).val();
                          $('#product_data').DataTable().destroy();
    
                          if(category != '')
                          {
                           load_data(category);
                          }
                          else
                          {
                           load_data();
                          }
                         });
    
    
    
                      // affiche plus de détaille annonce 
                      function format ( d ) {
                          if ( d[5] == '') {
                            $online = '<div class="steamWidget no-steam">'+
                                      'Statut Steam: <p>Steam Non renseigné</p><br><br>'+
                                      'Description Prochainement</div>';
    
                          } else {
    
                            if ( d[5] == 'online') {
                                  $online = '<div class="steamWidget online">'+
                                            'Statut Steam:<p>'+d[5]+'</p><br><br>'+
                                            'Description Prochainement</div>';
                                }
                                else  {
                                    $online = '<div class="steamWidget offline">'+
                                              'Statut Steam:<p>'+d[5]+'</p><br><br>'+
                                              'Description Prochainement</div>'; 
                                }
    
                          }
                          return $online;
                      }
    
                        // affiche plus de détaille annonce suite
                      $(document).on('click', 'td.details-control', function () {
                          var tr = $(this).closest('tr');
                          var row = 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');
                          }
                      });
    
                      // affiche plus de détaille annonce 
                      function format ( d ) {
                          if ( d[5] == '') {
                            $online = '<div class="steamWidget no-steam">'+
                                      'Statut Steam: <p>Steam Non renseigné</p><br><br>'+
                                      'Description Prochainement</div>';
    
                          } else {
    
                            if ( d[5] == 'online') {
                                  $online = '<div class="steamWidget online">'+
                                            'Statut Steam:<p>'+d[5]+'</p><br><br>'+
                                            'Description Prochainement</div>';
                                }
                                else  {
                                    $online = '<div class="steamWidget offline">'+
                                              'Statut Steam:<p>'+d[5]+'</p><br><br>'+
                                              'Description Prochainement</div>'; 
                                }
    
                          }
                          return $online;
                      }
    
                   }
    
    
              });
    
  • colincolin Posts: 15,144Questions: 1Answers: 2,586

    Hi @laurent09 ,

    The problem is still the same, it hasn't been fixed, the same error is in the console.

    As I said in my last comment, whenever the game is changed, you're creating more and more event handlers like this

    $(document).on('click', 'td.details-control', function() {
      ...
    }
    

    You're just adding more and more to the list of event handlers whenever the data is loaded. So by the time you've changed the game twice, that will trigger twice when the '+' is clicked on, and this is causing problems.

    The suggestions I made in that last comment will fix it. Hope that helps explain it,

    Cheers,

    Colin

  • laurent09laurent09 Posts: 18Questions: 0Answers: 0
    edited May 2018

    ok i'm trying to understand i'm sorry but i dont arrive

    I saw that every time I send something to my table I have a fetch.php that create it, and when I change games it is not delete it create a second and a third. ..

    I am completely lost.

  • laurent09laurent09 Posts: 18Questions: 0Answers: 0

    I add " dataTable.ajax.reload(); " when I close the row.child
    it works but it's not perfect yet.

      // affiche plus de détaille annonce suite
    $(document).on('click', 'td.details-control', function () {
        var tr = $(this).closest('tr');
        var row = dataTable.row( tr );
    
        if ( row.child.isShown() ) {
            // This row is already open - close it
            row.child.hide();
            tr.removeClass('shown');
    
            dataTable.ajax.reload();
    
        }
        else {
            // Open this row
            row.child( format(row.data()) ).show();
            tr.addClass('shown');
        }
    } );
    
  • colincolin Posts: 15,144Questions: 1Answers: 2,586
    edited May 2018

    Hi @laurent09 ,

    Your problem is that you're still calling the event handler multiple times.

    Take a look at this very simple example here - the code is very similar to yours. You initialise the data at the start (loadData in your case) and then you create an event handler in that function. But, every time that function is called, you're creating more and more event handlers - see how the count is increasing in my example.

    If you look at my message that starts, "We worked it out.", this explains how to avoid the problem and what steps to take.

    Cheers,

    Colin

  • laurent09laurent09 Posts: 18Questions: 0Answers: 0

    yes i saw that my function " load_data(); " create each time a fetch.php
    but I dont arrive to replace .destroy(); by .ajax.reload() or .clear() I have errors.

    can I reload the function load_data ()?

  • allanallan Posts: 61,726Questions: 1Answers: 10,110 Site admin

    You don't really need to destroy the table. Indeed, you should only destroy the table if you want to change its structure (e.g. different columns) since there is a fair bit of processing overhead in destroying and then creating a new table.

    What I would suggest is that you create the table and add the event handlers only once. Do it with the ajax.data option as a function rather than as a static object as you currently have. The advantage of a function is that it will evaluate every time the table's Ajax triggers, so you can reference an external variable:

           "ajax":{
            url:"includes/fetch.php",
            type:"POST",
            data: function ( d ) {
              d.is_category = is_category;
            }
           },
    

    Then to reload the table with different data all you need to do is:

    is_category = ...;
    table.draw();
    

    Allan

  • laurent09laurent09 Posts: 18Questions: 0Answers: 0

    ok thank you very much, it works I think.
    how can I load all the table without category?
    I have to do a .ajax.reload (); ?

        // change la catégorie
       $(document).on('change', '#category', function(){
        var category = $(this).val();
        if(category != '')
        {
         is_category = category;
            dataTable.draw();
        }
        else
        {
            dataTable.draw();
        }
       });
    
  • laurent09laurent09 Posts: 18Questions: 0Answers: 0

    it's possible to reload my tables?

    I tried it with "ajax.reload ();" at the line 91, but it does not work.

      $(document).ready(function (){
    
        load_data();
    
        function load_data(is_category) {
    
            var dataTable = $('#product_data').DataTable({
              "iDisplayLength": 15,
              "processing":true,
              "serverSide":true,
              "order":[],
              ajax:{
                    url:"includes/fetch.php",
                    type:"POST",
                    data: function ( d ) {
                        d.is_category = is_category;
                  }
                },
              "columns": [
                      {
                          "className":      'details-control',
                          "orderable":      false,
                          "data":           null,
                          "defaultContent": ''
                      },
                      { "data": 1},
                      { "data": 2},
                      { "data": 3,
                        "orderable":false,},
                      { "data": 4 }
                ],
              "language": {
                   "processing": "<div id='loader'></div>"
                }
            });
    
    
            // affiche plus de détaille annonce 
            function format ( d ) {
                if ( d[5] == '') {
                  $online = '<div class="steamWidget no-steam">'+
                            'Statut : <p> Non renseigné</p><br><br>'+
                            'Description Prochainement</div>';
    
                } else {
    
                  if ( d[5] == 'online') {
                        $online = '<div class="steamWidget online">'+
                                  'Statut :<p></p><br><br>'+
                                  'Description Prochainement</div>';
                      }
                      else  {
                          $online = '<div class="steamWidget offline">'+
                                    'Statut :<p></p><br><br>'+
                                    'Description Prochainement</div>'; 
                      }
    
                }
                return $online;
            }
    
            // affiche plus de détaille annonce suite
            $(document).on('click', 'td.details-control', function () {
                var tr = $(this).closest('tr');
                var row = 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');
    
                }
            } );
    
              // change la catégorie
            $(document).on('change', '#category', function(){
              var category = $(this).val();
              if(category != 0)
              {
               is_category = category;
                  dataTable.draw();
              }
              else
              {
    
                  dataTable.ajax.reload();
              }
             });
    
        }
    
      });
    
  • kthorngrenkthorngren Posts: 20,309Questions: 26Answers: 4,770

    What happens with dataTable.ajax.reload();?

    Do you get any errors?

    My guess is the the variable `dataTable is local to the load_data function:

      function load_data(is_category) {
     
          var dataTable = $('#product_data').DataTable({
    

    You probably should declare it globally, something like this:

    var dataTable;
    $(document).ready(function (){
     
      load_data();
     
      function load_data(is_category) {
     
          dataTable = $('#product_data').DataTable({
    

    And remove var from inside the function. If this doesn't help please be more specific of what is not working.

    Kevin

  • laurent09laurent09 Posts: 18Questions: 0Answers: 0

    OK
    I tried but it does not change anything.

    I have no errors.
    when I change the category to " touts les jeux ", it does not work, nothing happens.
    I would like to reload the table to display all my data without category, as when I refresh my page the first time.

    1 change to "arma 3"
    2 change to "touts les jeux"
    http://ckdn.esy.es/

  • kthorngrenkthorngren Posts: 20,309Questions: 26Answers: 4,770
    edited May 2018

    Looks like the ajax.reload part of the code is working. The problem is with the request.

    When selecting "arma 3" the request has this (from the browser's dev tools):

    draw: 4
    columns[0][data]: 
    .......
    start: 0
    length: 15
    search[value]: 
    search[regex]: false
    is_category: 36
    

    Category 36.

    Next I select "touts les jeux" and the request looks like this - its the next requests as the draw parameter incremented:

    draw: 5
    columns[0][data]: 
    ........
    start: 0
    length: 15
    search[value]: 
    search[regex]: false
    is_category: 36
    

    But it has category 36, same as the previous. You will need to adjust your Javascript code to provide a category value that will allow you to get all records. And you will need to adjust your server code to handle that particular value the way you want. Again the ajax.reload is working as expected.

    Kevin

  • laurent09laurent09 Posts: 18Questions: 0Answers: 0

    thank you very much everyone for your help I ended up successful
    like this

              // change la catégorie
            $(document).on('change', '#category', function(){
              var category = $(this).val();
              if(category != 0)
              {
               is_category = category;
                  dataTable.draw();
              }
              else
              {
    
                  is_category = "all";
                  dataTable.draw();
              }
             });
    

    and in my fetch.php

            if($_POST["is_category"] != "all")
            {
                $query .= " id = '".$_POST["is_category"]."' AND ";
            }
            else
            {
                $query .= " ";
            }
    

    thanks

This discussion has been closed.