jQuery DataTables: How to add a checkbox column

Update
January 15, 2016
See jQuery DataTables Checkboxes plug-in that makes it much easier to add checkboxes and multiple row selection to a table powered by jQuery DataTables. It works in client-side and server-side processing modes, supports alternative styling and other extensions.

Example

Client-side processing mode with Ajax sourced data

Example below shows a table in client-side processing mode where data is received from the server via Ajax request.

Name Position Office Extn. Start date Salary
Name Position Office Extn. Start date Salary

Data submitted to the server:


$(document).ready(function (){
   var table = $('#example').DataTable({
      'ajax': {
         'url': '/lab/articles/jquery-datatables-how-to-add-a-checkbox-column/ids-arrays.txt' 
      },
      'columnDefs': [{
         'targets': 0,
         'searchable': false,
         'orderable': false,
         'className': 'dt-body-center',
         'render': function (data, type, full, meta){
             return '<input type="checkbox" name="id[]" value="' + $('<div/>').text(data).html() + '">';
         }
      }],
      'order': [[1, 'asc']]
   });

   // Handle click on "Select all" control
   $('#example-select-all').on('click', function(){
      // Get all rows with search applied
      var rows = table.rows({ 'search': 'applied' }).nodes();
      // Check/uncheck checkboxes for all rows in the table
      $('input[type="checkbox"]', rows).prop('checked', this.checked);
   });

   // Handle click on checkbox to set state of "Select all" control
   $('#example tbody').on('change', 'input[type="checkbox"]', function(){
      // If checkbox is not checked
      if(!this.checked){
         var el = $('#example-select-all').get(0);
         // If "Select all" control is checked and has 'indeterminate' property
         if(el && el.checked && ('indeterminate' in el)){
            // Set visual state of "Select all" control 
            // as 'indeterminate'
            el.indeterminate = true;
         }
      }
   });

   // Handle form submission event
   $('#frm-example').on('submit', function(e){
      var form = this;

      // Iterate over all checkboxes in the table
      table.$('input[type="checkbox"]').each(function(){
         // If checkbox doesn't exist in DOM
         if(!$.contains(document, this)){
            // If checkbox is checked
            if(this.checked){
               // Create a hidden element 
               $(form).append(
                  $('<input>')
                     .attr('type', 'hidden')
                     .attr('name', this.name)
                     .val(this.value)
               );
            }
         } 
      });
   });

});

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
//cdn.datatables.net/1.10.7/js/jquery.dataTables.min.js

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

//cdn.datatables.net/1.10.7/css/jquery.dataTables.min.css

Edit on jsFiddle

Highlights

Javascript

  • Columns definition

          'columnDefs': [{
             'targets': 0,
             'searchable':false,
             'orderable':false,
             'className': 'dt-body-center',
             'render': function (data, type, full, meta){
                 return '<input type="checkbox" name="id[]" value="' + $('<div/>').text(data).html() + '">';
             }
          }],
    

    Option columnsDef is used to define appearance and behavior of the first column ('targets': 0).

    Searching and ordering of the column is not needed so this functionality is disabled with searchable and orderable options.

    To center checkbox in the cell, internal DataTables CSS class dt-body-center is used.

    Option render is used to prepare the checkbox control for being displayed in each cell of the first column. We use a trick with $('<div/>').text(data).html() to encode HTML entities that could be present in the data.

    Another trick here is to give input element a name with square brackets (id[]). This will make handling of list of checked checkboxes easier on the server-side. For example, PHP will convert all these parameters to an array, see PHP FAQ: How do I get all the results from a select multiple HTML tag for more information.

  • Initial sorting order

          'order': [[1, 'asc']],
    

    By default, DataTables sorts the table by first column in ascending order. By using order option we select another column to perform initial sort.

  • “Select all” control

       // Handle click on "Select all" control
       $('#example-select-all').on('click', function(){
          // Get all rows with search applied
          var rows = table.rows({ 'search': 'applied' }).nodes();
          // Check/uncheck checkboxes for all rows in the table
          $('input[type="checkbox"]', rows).prop('checked', this.checked);
       });
    

    We attach event handler to handle clicks on “Select all” control. To retrieve all checkboxes that are present in the table taking into account currently applied filter, we use rows() method using appropriate selector-modifier.

       // Handle click on checkbox to set state of "Select all" control
       $('#example tbody').on('change', 'input[type="checkbox"]', function(){
          // If checkbox is not checked
          if(!this.checked){
             var el = $('#example-select-all').get(0);
             // If "Select all" control is checked and has 'indeterminate' property
             if(el && el.checked && ('indeterminate' in el)){
                // Set visual state of "Select all" control 
                // as 'indeterminate'
                el.indeterminate = true;
             }
          }
       });
    

    The purpose of the event handler above is to detect when one of the checkboxes in the table is unchecked when “Select all” control was checked. When that happens, we can set “Select all” control to a special state indeterminate to indicate that only some checkboxes are checked.

  • Form submission

       // Handle form submission event
       $('#frm-example').on('submit', function(e){
          var form = this;
    
          // Iterate over all checkboxes in the table
          table.$('input[type="checkbox"]').each(function(){
             // If checkbox doesn't exist in DOM
             if(!$.contains(document, this)){
                // If checkbox is checked
                if(this.checked){
                   // Create a hidden element 
                   $(form).append(
                      $('<input>')
                         .attr('type', 'hidden')
                         .attr('name', this.name)
                         .val(this.value)
                   );
                }
             } 
          });
       });
    

    When table is enhanced by jQuery DataTables plug-in, only visible elements exist in DOM. That is why by default form submits checkboxes from current page only.

    To submit checkboxes from all pages we need to retrieve them with $() API method. Then for each checkbox not present in DOM we add a hidden element to the form with the same name and value. This allows all the data to be submitted.

    It’s even more simple if form submission is performed via Ajax. In that case URL-encoded data for submission can be produced using the code below:

    var data = table.$('input[type="checkbox"]').serialize();

    For more information on submitting the form elements in a table powered by jQuery DataTables, please see jQuery DataTables: How to submit all pages form data.

Server-side processing

Please note that the example and code above will work for client-side processing mode only.

In server-side processing mode ('serverSide':true) elements <input type="checkbox"> would exist for current page only. Once page is changed, the checked state of the checkboxes would not be preserved.

See jQuery DataTables Checkboxes for a universal solution that will work for server-side processing mode as well.

You May Also Like

Comments

  1. Thank you very much. Is it possible to select specific no. of rows, e.g. if we want to select top 5 rows.

  2. Thanks a lot! This was exactly what I needed and worked very smoothly, very much appreciated! You’ve saved me hours of work

  3. I’ve got this working, great example so thank you for that.

    I have a different use for this though, I am returning true/false values from server side and displaying checkboxes which is working fine.

    How can I sort and filter against this? So either sort to show all checked at the top of filter just checked or just unchecked.

    I changed the render to this to display tick the checkbox

    return '';
  4. Hi

    I’ve got working great in terms of have checked, unchecked and indeterminate

    Is it possible to sort by what is checked without filtering?

    Here’s the filter which I’m passing in the column and the state, how could I modify this to order or sort.

    
    $.fn.dataTable.ext.search.pop();
        $.fn.dataTable.ext.search.push(
            function CheckBoxColumnFilter(settings, data, dataIndex) {
                if (settings.aoData[dataIndex]._aData[currentColumn] == state)
                    return true;
    
                return false;
            }
        );
    
  5. Hi

    I’ve got this working now, seems to do the trick by setting the column def type to a custom order

    The value ‘d’ in the sort is “”
    So then turn that into a jquery object to get the value and return the respective value.

    
    
    $.fn.dataTable.ext.type.order['checkSort-pre'] = function (d) {
    	switch ($(d).val()) {
    		case 'true': return 1;
    		case 'false': return 2;
    	}
    	return 0;
    };
    	
    

    Couldn’t have got all this sorted without this site, really appreciated.

  6. Hi, I want to add more checkbox columns into the table. And I want to get status of each checkbox also. How can i do it? Thank you.

  7. It looks great.. But what kind for json data format required as a response. can you provide example data file ?

  8. Thank you for your solution!

    Little addition to make #example-select-all selected back after row is selected again after deselecting (sounds complicated:-) )

    Consider to convert from typescript to js if needed

    $('#example tbody').on('change', 'input[type="checkbox"]', function() {
              // If checkbox is not checked
              const el = $('#example-select-all').get(0) as HTMLInputElement;
              // Get all rows with search applied
              const rows = dtInstance.rows({ 'search': 'applied' }).nodes();
              const selects = $('input[type="checkbox"]', rows).toArray().map(select => select.checked);
              // If "Select all" control is checked and has 'indeterminate' property
              if (el && ('indeterminate' in el)) {
                // at least one selected
                if (selects.indexOf(true) > -1) {
                  // if all selected
                  el.indeterminate = true;
                  if (selects.indexOf(false) === -1) {
                    el.indeterminate = false;
                    el.checked = true;
                  }
                } else {
                  // nothing selected
                  el.indeterminate = false;
                  el.checked = false;
                }
              }
            });
  9. My table has 2 headings rows and for some reason it didn’t appeared a check box in any of them. Suggestions?

  10. Very nice articles about check boxes in Jquery data table server side. it helps a lot for me. Thanks!

  11. Michael Ryvkin

    Hi, I have an error,

    dataTables.checkboxes.min.js:5 Uncaught TypeError: Cannot read property ‘Api’ of undefined
    at dataTables.checkboxes.min.js:5
    at dataTables.checkboxes.min.js:5
    at dataTables.checkboxes.min.js:5
    (anonymous) @ dataTables.checkboxes.min.js:5
    (anonymous) @ dataTables.checkboxes.min.js:5
    (anonymous) @ dataTables.checkboxes.min.js:5

    when I am trying to use this plugin, may be because I am manually creating the tabledata after getting data from the API in the code itself and appending it to the table body I need to know how to do this?because I am not using the “ajax” atribute. The code looks like this for me
    //my checkbox is in the last row and its actually to get the ‘verified’ property yes/no of a column and not for selecting rows but I need to preserve the checkbox state using saveState during pagination.

    var table=  jQuery_2_2_2('#reporttable').DataTable({
        	  
        	  'stateSave': true,
        	  'columnDefs': [
    	          {
    	             'targets': 19,
    	             'checkboxes': {
    	                'selectRow': true
    	             }
    	          }
    	       ],
    	       'select': 'multi',
        	 
            	    dom: 'Bfrtip',
            	    scrollY:        true,
    			    scrollX:        true,
    			    scrollCollapse: true,
    			    fixedColumns:   {
    			        leftColumns: 1,
    			        rightColumns: 1
    			    },
    			      
            	    buttons: [{
            	        extend: 'copyHtml5',
            	        exportOptions: {
            	          orthogonal: 'export'
            	        }
            	      },
            	      {
            	        extend: 'excelHtml5',
            	        exportOptions: {
            	          orthogonal: 'export',
            	          format: {
            	            body: function(data, row, column, node) {
            	              
            	              
    
            	              if (column === 19) {
            	               data = $(node).children().data("checked");
            	              }
            	              return data;
            	            }
            	          }
            	        }
            	      },
            	      {
            	        extend: 'pdfHtml5',
            	        exportOptions: {
            	          orthogonal: 'export'
            	        }
            	      }
            	    ]
    
            	  });//.datatable
    
  12. Is there any thing else which is conflicting in my code as I am using many diff plugins and version of data tables js and css files for different features? Because I am getting the expected behavior when I just write this removing the other options of the datatable.

      var table=  jQuery_2_2_2('#reporttable').DataTable({
        	  
        	  'stateSave': true,
        	  'columnDefs': [
    	          {
    	             'targets': 19,
    	             'checkboxes': {
    	                'selectRow': true
    	             }
    	          }
    	       ],
    	       'select': 'multi'
    This is working..but
    var table=  jQuery_2_2_2('#reporttable').DataTable({
        	  
        	  'stateSave': true,
        	  'columnDefs': [
    	          {
    	             'targets': 19,
    	             'checkboxes': {
    	                'selectRow': true
    	             }
    	          }
    	       ],
    	       'select': 'multi',
        	 
            	    dom: 'Bfrtip',
            	    scrollY:        true,
    			    scrollX:        true,
    			    scrollCollapse: true,
    			    fixedColumns:   {
    			        leftColumns: 1,
    			        rightColumns: 1
    			    },
    			      
            	    buttons: [{
            	        extend: 'copyHtml5',
            	        exportOptions: {
            	          orthogonal: 'export'
            	        }
            	      },
            	      {
            	        extend: 'excelHtml5',
            	        exportOptions: {
            	          orthogonal: 'export',
            	          format: {
            	            body: function(data, row, column, node) {
            	              
            	              
    
            	              if (column === 19) {
            	               data = $(node).children().data("checked");
            	              }
            	              return data;
            	            }
            	          }
            	        }
            	      },
            	      {
            	        extend: 'pdfHtml5',
            	        exportOptions: {
            	          orthogonal: 'export'
            	        }
            	      }
            	    ]
    
            	  });//.datatable
    

    This is not working.

  13. Hello, thank you for your tutorials. I managed to code what I wanted but I block on the selection of all checkboxes (data from an SQL query). I would like to retrieve all IDs from checked checkboxes and save them to a variable for further processing.
    Thank you for you precious help
    cordially

  14. foreach ($contacts as $contact) {
    echo ”;
    echo ‘ getId()).'”/> ‘;

    $(document).ready(function (){   
    
    
    		   var table = $('#example').DataTable({
    		      //'ajax': 'https://api.myjson.com/bins/1us28',  
    		      'columnDefs': [{
    		         'targets': 0,
    		         'searchable':false,
    		         'orderable':false,
    		         'className': 'dt-body-center',
    		         'render': function (data, type, full, meta){
    		             return '<input type="checkbox" name="id[]" value="' 
    		                + $('').text(data).html() + '">';
    		         }
    		      }],
    		      'order': [1, 'asc']
    		   });
    
    
    
    		   // Handle click on "Select all" control
    		   $('#example-select-all').on('click', function(){
    		      // Check/uncheck all checkboxes in the table
    		      var rows = table.rows({ 'search': 'applied' }).nodes();
    		      $('input[type="checkbox"]', rows).prop('checked', this.checked);
    		   });
    
    
    
    		   // Handle click on checkbox to set state of "Select all" control
    		   $('#example tbody').on('change', 'input[type="checkbox"]', function(){
    		      // If checkbox is not checked
    		      if(!this.checked){
    		         var el = $('#example-select-all').get(0);
    		         // If "Select all" control is checked and has 'indeterminate' property
    		         if(el && el.checked && ('indeterminate' in el)){
    		            // Set visual state of "Select all" control 
    		            // as 'indeterminate'
    		            el.indeterminate = true;
    		         }
    		      }
    		   });
    
    
    		    
    		   $('#Form_SearchMulti').on('submit', function(e){
    		      var form = this;
    
    		      // Iterate over all checkboxes in the table
    		      table.$('input[type="checkbox"]').each(function(){
    		         // If checkbox doesn't exist in DOM
    		         if(!$.contains(document, this)){
    		            // If checkbox is checked
    		            if(this.checked){
    		               // Create a hidden element 
    		               $(form).append(
    		                  $('')
    		                     .attr('type', 'hidden')
    		                     .attr('name', this.name)
    		                     .val(this.value)
    		               );
    		            }
    		         } 
    		      });
    
    		      // FOR TESTING ONLY
    		      
    		      // Output form data to a console
    		      $('#example-console').text($(form).serialize()); 
    		      console.log("Form submission", $(form).serialize()); 
    		       
    		      // Prevent actual form submission
    		      e.preventDefault();
    		   });
    });
    
    
    		
    
    

Leave a Reply

(optional)

This site uses Akismet to reduce spam. Learn how your comment data is processed.