Generate child row using ajax and display its content

Generate child row using ajax and display its content

mastro_dinomastro_dino Posts: 8Questions: 2Answers: 0

Hi, this is what I've done so far:

//generate table
    $(document).ready(function() {
        
        var table = $('#example').DataTable( {
            "ajax": {
                "url": "../contents/cbk-data-process.php",
                "async": false,
                "data": {"method": "product-list", 
                         "node": "$node"},
                "dataType": "json",
                "dataSrc": 'rpcresult',
                "type": "POST"
            },
            columns: [{
                className: 'nutrival',
                orderable: false,
                data: null,
                defaultContent: '',
                render: function(){
                    return '<i class="fa fa-plus-square" aria-hidden="trued"></i>'}
            },
                {data: "pcode" }],
          "order": [[1, 'asc']]
        
    } );

//open-close child row
    $('#example tbody').on('click', 'td.nutrival', function () {
        var tr = $(this).closest('tr');
        //var tdi = tr.find("i.fa");
        var row = table.row(tr);
     
        if ( row.child.isShown()) {                 //close row if open
            row.child.hide();
            tr.removeClass('shown');
            //tdi.first()removeClass('fa-minus-square');
            //tdi.first()addClass('fa-plus-square');
        }
        else {                                      //open row
            row.child(nutrival(row.data()) ).show();
            tr.addClass('shown');
            //tdi.first()removeClass('fa-plus-square');
            //tdi.first()addClass('fa-minus-square');
        }
    } );    
    } );

//working ajax call to server which contains elements to display in the child row
    function nutrival ( rowData ) {
        var div = $('<div/>')
            .addClass( 'loading' )
            .text( 'Loading...' );
     
        $.ajax( {
            "url": "../contents/cbk-data-process.php",
                "async": false,
                "data": {"method": "nutritional-values",
                         "node": "1", 
                         "pcode": "30001"},
                "dataType": "json",
                "dataSrc": 'rpcresult',
                "type": "POST",
            success: function ( json ) {
                div
                    .html( json.html )
                    .removeClass( 'loading' );
            },
            columns: [
                {data: "AntiOx" },
                {data: "Calories" },
                {data: "Carbs" },
                {data: "Fats" },
                {data: "Fibers" },
                {data: "Lipides" },
                {data: "Proteins" },
                {data: "Sat_fats" },
                {data: "Sodium" },
                {data: "Sugars" }
                ]
        } );
     
        return div;
    }

//function that should display the actual child elements but is stuck on loading... instead
    function format(d){
        
        // `d` is the original data object for the row
        return '<table cellpadding="5" cellspacing="0" border="0" style="padding-left:50px;">' +
            '<tr>' +
                '<th>AntiOx:</th>' +
                '<th>Calories:</th>' +
                '<th>Carbs:</th>' +
                '<th>...</th>' +
            '</tr>' +
        '</table>';  
   }

Both ajax calls are fine, I checked the browser log.
As I said in the title, I don't understand how the content is displayed and what should I do to make this work

This question has an accepted answers - jump to answer

Answers

  • kthorngrenkthorngren Posts: 20,264Questions: 26Answers: 4,764

    See if this blog about ajax loaded detail rows helps.

    Kevin

  • mastro_dinomastro_dino Posts: 8Questions: 2Answers: 0

    Thank you kthorngren, that is what I used as reference.
    What I'd like to understand is how the data from the second ajax request should be displayed as a child row.
    Right now when I click to open the child row the table shows a "Loading.." message, the request is sent and the server sends back the response but the "Loading..." message doesn't go away and the child row doesn't appear.

  • mastro_dinomastro_dino Posts: 8Questions: 2Answers: 0

    For completeness this is the result of the first request (all pcodes are displayed correctly in the table):

    {"status":0,"rpcresult":
    [{"key":"10","pcode":"30001"},{"key":"11","pcode":"30002"},{"key":"12","pcode":"30003"},{"key":"13","pcode":"30004"},{"key":"14","pcode":"30005"},{"key":"15","pcode":"30006"},{"key":"16","pcode":"30007"},{"key":"17","pcode":"30008"},{"key":"18","pcode":"30009"},{"key":"19","pcode":"30010"},{"key":"1A","pcode":"30011"}]}
    

    this is the result of the second one:

    {"status":0,"rpcresult":{"AntiOx":10,"Calories":22222,"Carbs":11,"Fats":0,"Fibers":0,"Lipides":44,"Proteins":0,"Sat_fats":0,"Sodium":99,"Sugars":0}}
    
  • tangerinetangerine Posts: 3,348Questions: 36Answers: 394

    I don't see where you're calling your "format" function.

  • kthorngrenkthorngren Posts: 20,264Questions: 26Answers: 4,764

    The columns you have defined in line 68 is not doing anything. You are using jQuery ajax to fetch the data not Datatables.

    The code in line 64 will update the div with the JSON response and remove the loading message. My guess is that there is an error with json.html because you don't have an html property. Look at the browsers console for errors.

                    div
                        .html( json.html )
                        .removeClass( 'loading' );
    

    You will need to change json.html to match the structure returned from the server. Use the browser's network inspector tool on the blog page. Look at the XHR response when opening one of the child rows. You will see something like this:

    {"html":"Details for <b>Brenden Wagner<\/b><br><br>Full information could be derived from a database and potentially complex interactions such as charts, DataTables or other controls could be shown if required. In this demo only this summary is returned."}

    You will need to change the code in the success function to parse and display the response you are getting. There are no Datatables requirements for this. You just need to build proper HTML.

    Kevin

  • mastro_dinomastro_dino Posts: 8Questions: 2Answers: 0
    edited September 2021

    Thank you Kevin for bearing with my incompetence.
    As you can see in my previous comment, when opening one of the child rows I recive a JSON literal and I'm really not sure how to handle this inside
    success: function ( json ) .
    Do I remove this entirely?

    div
     .html( json.html ) 
     .removeClass( 'loading' );
    

    Can I generate another table inside the child row using this JSON data? Sorry but I still don't get how this div part works :(

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

    Do I remove this entirely?

    That would be a good place to put the code to create the child row, so probably not.

    Can I generate another table inside the child row using this JSON data? Sorry but I still don't get how this div part works

    You can, but you need to format. If you're getting back the JSON for the data, you would need to construct that child to use that data, adding in the HTML to get the formatting you want.

    Colin

  • mastro_dinomastro_dino Posts: 8Questions: 2Answers: 0

    UPDATE: my JS now looks like this

    $(document).ready(function() {
        var table = $('#pcodes').DataTable( {
                "ajax": {
                    "url": "../contents/cbk-data-process.php",
                    "async": false,
                    "data": {"method": "product-list", 
                             "node": "$node"},
                    "dataType": "json",
                    "dataSrc": 'rpcresult',
                    "type": "POST"},
                columns: [{
                    className: 'empty',
                    order: false,
                    orderable: false,
                    data: null,
                    defaultContent: ''},
                    
                    {className: 'nutrival',
                    orderable: false,
                    data: null,
                    defaultContent: '',
                    render: function(){
                        return '<i class="fa fa-plus-square" aria-hidden="trued"></i>'}
                },
                
                    {data: "pcode" }],
              "order": [[2, 'asc']],
              "columnDefs": [{ "width": "45%", "targets": 0 }]
        } );
    
    //event listener
        $('#pcodes tbody').on('click', 'td.nutrival', function () {
            var tr = $(this).closest('tr');
            //var tdi = tr.find("i.fa");
            var row = table.row( tr );
            var rowData = row.data();
    
    //child table index
            var index = row.index();
            console.log(index);
             
            if ( row.child.isShown() ) {                    
                //close row if open
                row.child.hide();
                tr.removeClass('shown');
                //tdi.first()removeClass('fa-minus-square');
                //tdi.first()addClass('fa-plus-square');
            }
            else {                                      
                //open row
                row.child(
                    '<table id = "nutrival" cellpadding="5" stripe="0" cellspacing="0" border="0" style="padding-left:50px;">'+
                    '<thead><tr><th>Antioxidants</th><th>Calories</th><th>Carbohydrates</th><th>Fats</th><th>Fibers</th><th>Lipides</th><th>Proteins</th><th>Saturated fats</th><th>Sodium</th><th>Sugars</th></tr></thead><tbody>' +
                     '</tbody></table>').show();
                //tdi.first()removeClass('fa-plus-square');
                //tdi.first()addClass('fa-minus-square');
            var childTable = $('#nutrival').DataTable({
                    "ajax": {
                        "url": "../contents/cbk-data-process.php",
                        "async": false,
                        "data": {"method": "nutritional-values",
                                 "node": "1",
                                 "pcode": "30001"},
                        "dataType": "json",
                        "dataSrc": 'rpcresult',
                        "type": "POST"},
                        
                columns: [{data: "AntiOx" },
                          {data: "Calories" },
                          {data: "Carbs" },
                          {data: "Fats" },
                          {data: "Fibers" },
                          {data: "Lipides" },
                          {data: "Proteins" },
                          {data: "Sat_fats" },
                          {data: "Sodium" },
                          {data: "Sugars" }],
    
                "paging": false,
                "ordering": false,
                "info": false,
                "searching": false,
                    
                      destroy: true,
                        scrollY: '50px'
                      });
                        tr.addClass('shown');
                    }
                } );
            } );
    

    Still not able to display #nutrival data, I guess it has something to do with the JSON that the server is sending. Any help would be highly appreciated

  • kthorngrenkthorngren Posts: 20,264Questions: 26Answers: 4,764

    This blog will show how to display the child row as a Datatable. It also shows how to incorporate the Editor. You can ignore this portion of the code if you aren't using Editor for the child rows.

    Kevin

  • mastro_dinomastro_dino Posts: 8Questions: 2Answers: 0
    edited September 2021

    Thanks everyone but now I'm 99% sure my problem is with the JSON from the second ajax request. Since it's just a simple object and not an array of objects I guess Datatable can't process it and it's not able to fill my single-row table.
    Do you know if there is a way to make Datatable accept the object or do I have to convert it forcefully in an array?

  • kthorngrenkthorngren Posts: 20,264Questions: 26Answers: 4,764
    Answer ✓

    The ajax option expects an array of row data. You can use ajax.dataSrc as a function to return the single row of data in an array. Or return the data in an array from your server script.

    Kevin

Sign In or Register to comment.