jQuery DataTables: Responsive extension and custom controls

Problem

Table below demonstrates the problem with table containing custom controls and Responsive extension.

To replicate the problem, perform the following steps:

  • Reduce window size so that Rating column becomes hidden.
  • Click on green (+) icon to show additional details. Star rating control will not be shown.
Name Position Office Age Rating Salary
Name Position Office Age Rating Salary
Tiger Nixon System Architect Edinburgh 61 $320,800
Garrett Winters Accountant Tokyo 63 $170,750
Ashton Cox Junior Technical Author San Francisco 66 $86,000
Bradley Greer Software Engineer London 41 $132,000
Dai Rios Personnel Lead Edinburgh 35 $217,500
Jenette Caldwell Development Lead New York 30 $345,000
Yuri Berry Chief Marketing Officer (CMO) New York 40 $675,000
Caesar Vance Pre-Sales Support New York 21 $106,450
Doris Wilder Sales Assistant Sidney 23 $85,600
Angelica Ramos Chief Executive Officer (CEO) London 47 $1,200,000
Gavin Joyce Developer Edinburgh 42 $92,575
Jennifer Chang Regional Director Singapore 28 $357,650
Brenden Wagner Software Engineer San Francisco 28 $206,850
Fiona Green Chief Operating Officer (COO) San Francisco 48 $850,000
Shou Itou Regional Marketing Tokyo 20 $163,000
Michelle House Integration Specialist Sidney 37 $95,400
Suki Burks Developer London 53 $114,500
Prescott Bartlett Technical Author London 27 $145,000
Gavin Cortez Team Leader San Francisco 22 $235,500
Martena Mccray Post-Sales support Edinburgh 46 $324,050
Unity Butler Marketing Designer San Francisco 47 $85,675
Howard Hatfield Office Manager San Francisco 51 $164,500
Hope Fuentes Secretary San Francisco 41 $109,850
Vivian Harrell Financial Controller San Francisco 62 $452,500
Timothy Mooney Office Manager London 37 $136,200
Jackson Bradshaw Director New York 65 $645,750
Olivia Liang Support Engineer Singapore 64 $234,500
Bruno Nash Software Engineer London 38 $163,500
Sakura Yamamoto Support Engineer Tokyo 37 $139,575
Thor Walton Developer New York 61 $98,540
Finn Camacho Support Engineer San Francisco 47 $87,500
Serge Baldwin Data Coordinator Singapore 64 $138,575
Zenaida Frank Software Engineer New York 63 $125,250
Zorita Serrano Software Engineer San Francisco 56 $115,000
Jennifer Acosta Junior Javascript Developer Edinburgh 43 $75,650
Cara Stevens Sales Assistant New York 46 $145,600
Hermione Butler Regional Director London 47 $356,250
Lael Greer Systems Administrator London 21 $103,500
Jonas Alexander Developer San Francisco 30 $86,500
Shad Decker Regional Director Edinburgh 51 $183,000
Michael Bruce Javascript Developer Singapore 29 $183,000
Donna Snider Customer Support New York 27 $112,000

Cause

This problem occurs because Responsive extension performs rendering after the call to function defined by drawCallback option. Therefore custom control initialization performed in drawCallback with initRating() doesn’t see markup produced by renderer of Responsive extension and custom controls appear uninitialized.

This behavior is observed in Responsive extension versions 1.0.x and 2.0.0.

Solution

The solution is to override default renderer for Responsive extension, call default renderer to produce an output and initialize control before returning rendered output to jQuery DataTables to display. This can be achieved with the following code, see lines 10-20.

      responsive: {
         details: {
            renderer: function(api, rowIdx, columns){
               var $row_details = $.fn.DataTable.Responsive.defaults.details.renderer(api, rowIdx, columns);

               // Initialize custom control
               initRating($row_details);

               return $row_details;
            }
         }
      }

Table below demonstrates the working solution.

Name Position Office Age Rating Salary
Name Position Office Age Rating Salary
Tiger Nixon System Architect Edinburgh 61 $320,800
Garrett Winters Accountant Tokyo 63 $170,750
Ashton Cox Junior Technical Author San Francisco 66 $86,000
Bradley Greer Software Engineer London 41 $132,000
Dai Rios Personnel Lead Edinburgh 35 $217,500
Jenette Caldwell Development Lead New York 30 $345,000
Yuri Berry Chief Marketing Officer (CMO) New York 40 $675,000
Caesar Vance Pre-Sales Support New York 21 $106,450
Doris Wilder Sales Assistant Sidney 23 $85,600
Angelica Ramos Chief Executive Officer (CEO) London 47 $1,200,000
Gavin Joyce Developer Edinburgh 42 $92,575
Jennifer Chang Regional Director Singapore 28 $357,650
Brenden Wagner Software Engineer San Francisco 28 $206,850
Fiona Green Chief Operating Officer (COO) San Francisco 48 $850,000
Shou Itou Regional Marketing Tokyo 20 $163,000
Michelle House Integration Specialist Sidney 37 $95,400
Suki Burks Developer London 53 $114,500
Prescott Bartlett Technical Author London 27 $145,000
Gavin Cortez Team Leader San Francisco 22 $235,500
Martena Mccray Post-Sales support Edinburgh 46 $324,050
Unity Butler Marketing Designer San Francisco 47 $85,675
Howard Hatfield Office Manager San Francisco 51 $164,500
Hope Fuentes Secretary San Francisco 41 $109,850
Vivian Harrell Financial Controller San Francisco 62 $452,500
Timothy Mooney Office Manager London 37 $136,200
Jackson Bradshaw Director New York 65 $645,750
Olivia Liang Support Engineer Singapore 64 $234,500
Bruno Nash Software Engineer London 38 $163,500
Sakura Yamamoto Support Engineer Tokyo 37 $139,575
Thor Walton Developer New York 61 $98,540
Finn Camacho Support Engineer San Francisco 47 $87,500
Serge Baldwin Data Coordinator Singapore 64 $138,575
Zenaida Frank Software Engineer New York 63 $125,250
Zorita Serrano Software Engineer San Francisco 56 $115,000
Jennifer Acosta Junior Javascript Developer Edinburgh 43 $75,650
Cara Stevens Sales Assistant New York 46 $145,600
Hermione Butler Regional Director London 47 $356,250
Lael Greer Systems Administrator London 21 $103,500
Jonas Alexander Developer San Francisco 30 $86,500
Shad Decker Regional Director Edinburgh 51 $183,000
Michael Bruce Javascript Developer Singapore 29 $183,000
Donna Snider Customer Support New York 27 $112,000
$(document).ready(function() {
    var table = $('#example').DataTable({
        columnDefs: [
            { targets: 4, width: '100px' }
        ],
        drawCallback: function(settings){
            var api = this.api();

            // Initialize custom control
            initRating(api.table().container());
        },
        responsive: {
            details: {
                renderer: function(api, rowIdx, columns){
                    var $row_details = $.fn.DataTable.Responsive.defaults.details.renderer(api, rowIdx, columns);

                    // Initialize custom control
                    initRating($row_details);

                    return $row_details;
                }
            }
        }
    });
});


//
// Initializes jQuery Raty control
//
function initRating(container) {
    $('span.rating', container).raty({
        half: true,
        starHalf: 'https://cdnjs.cloudflare.com/ajax/libs/raty/2.7.0/images/star-half.png',
        starOff: 'https://cdnjs.cloudflare.com/ajax/libs/raty/2.7.0/images/star-off.png',
        starOn: 'https://cdnjs.cloudflare.com/ajax/libs/raty/2.7.0/images/star-on.png',
        readOnly: true,
        score: function() {
            return $(this).attr('data-score');
        }
    });
}

In addition to the above code, the following Javascript library files are loaded for use in this example:

//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js
https://cdn.datatables.net/r/dt/dt-1.10.9,r-1.0.7/datatables.min.js
https://cdnjs.cloudflare.com/ajax/libs/raty/2.7.0/jquery.raty.min.js

The following CSS library files are loaded for use in this example to provide the styling of the table:

https://cdn.datatables.net/r/dt/dt-1.10.9,r-1.0.7/datatables.min.css
https://cdnjs.cloudflare.com/ajax/libs/raty/2.7.0/jquery.raty.min.css

Edit on jsFiddle

Alternative solution

This solution will work only with Responsive extension 2.0.0 and up. In this version responsive-display event has been added which is triggered when details for a row have been displayed, updated or hidden.

The solution is to handle such event and initialize custom control in event handler as demonstrated below:

$(document).ready(function() {
    var table = $('#example').DataTable({
        columnDefs: [
            { targets: 4, width: '100px' }
        ],
        drawCallback: function(settings){
            var api = this.api();

            // Initialize custom control
            initRating(api.table().container());
        },
        responsive: true
    });
    
    table.on('responsive-display', function (e, api, row, showHide, update){
        // If row details are being shown
        if(showHide){
            // Get row containing details which follows the main row
            var $row_details = $(row.node()).next();
            
            // Initialize custom control
            initRating($row_details);
        }
    });
});

Edit on jsFiddle

Related posts

Comments

  1. Hello! In your initRating function you set the readOnly property to true, so nothing happens when trying to change the rating. Setting this to false will fix this. I apologize if I missed something. Thanks for your efforts!

    function initRating(container) {
        $('span.rating', container).raty({
            half: true,
            starHalf: 'https://cdnjs.cloudflare.com/ajax/libs/raty/2.7.0/images/star-half.png',
            starOff: 'https://cdnjs.cloudflare.com/ajax/libs/raty/2.7.0/images/star-off.png',
            starOn: 'https://cdnjs.cloudflare.com/ajax/libs/raty/2.7.0/images/star-on.png',
            readOnly: true,
            score: function() {
                return $(this).attr('data-score');
            }
        });
    }
    
    1. John, thanks for your suggestion. My goal was to show how initialize custom controls with Responsive extension. In the meantime specific configuration of the control is up to the developer, my article just shows read-only rating control as an example.

Leave a Reply

You may use simple HTML to add links or lists to your comment. Also use <pre><code class="language-*">...</code></pre> to mark up code snippets. We support language-js, language-markup and language-css for comments.
(Optional)