21
votes

Have this column in a Kendo grid that currently display a MySQL Boolean value so we have either 1 or 0.

Made this demo to play on...

This in an autosync and inline:true grid.

I would like this column to be of type "Checkbox" but, for some weird reasons, i just cannot find a demo or an example on the web that displays "enabled" checkbox that changes 1 to 0 when unchecked and Vice-Versa.

3

3 Answers

40
votes

There are some previous considerations:

  1. When you click in a cell for editing you are switching it to edit mode and then is when editor function get executed.
  2. If you are not in edition mode despite of the HTML used, the changes are not transferred in the model.
  3. Kendo UI render boolean as checkboxes for editing but not while not in edit mode.

What you need to do is:

  1. Define a template for displaying a checkbox.
  2. If you do not want to click twice the checkbox (the first to enter edit mode and the second to change it's value), you need to define a checkbox but bind a change event that intercepts clicks on it and change the model.

Template definition:

{
    title   : "Fully Paid",
    field   : "fullyPaid",
    template: "<input name='fullyPaid' class='ob-paid' type='checkbox' data-bind='checked: fullyPaid' #= fullyPaid ? checked='checked' : '' #/>"
}

As you can see I'm not defining an editor function since we will change the value of the checkbox without entering in edition mode.

Define a handler that detect changes in the checkbox that I defined in the template and update the model.

grid.tbody.on("change", ".ob-paid", function (e) {
    var row = $(e.target).closest("tr");
    var item = grid.dataItem(row);
    item.set("fullyPaid", $(e.target).is(":checked") ? 1 : 0);
});

Your JSBin modified here : http://jsbin.com/ebadaj/12/edit

17
votes

I had the same problem with my batch edited grid. The solutions I found were only for one specific column (as the solution mentioned above). So I changed

item.set("fullyPaid", $(e.target).is(":checked") ? 1 : 0);

to

var col = $(this).closest('td');
dataItem.set(grid.columns[col.index()].field, checked);

So you can use it for any checkbox columns.

The next problem was the dirty flag which is not set correctly when using the "one click edit" option of checkbox.

So I've tested various things to get it work and endet up with this:

In column definition:

.ClientTemplate("<input type='checkbox' #= CheckboxColumn? checked='checked': checked='' # class='chkbx' />");

And script below:

<script>
    $(function () {
        $('#GridName').on('click', '.chkbx', function () {
            var checked = $(this).is(':checked');
            var grid = $('#GridName').data().kendoGrid;
            grid.closeCell();
            var dataItem = grid.dataItem($(this).closest('tr'));
            var col = $(this).closest('td');
            grid.editCell(col);
            dataItem.set(grid.columns[col.index()].field, checked);
            grid.closeCell(col);
        });
    });
</script>
1
votes

Updated example for 2018!!

with themes. Kendo uses Themes so using the standard "browser-checkbox-look" (different in every browser) is not so nice.

https://dojo.telerik.com/IluJosiG/14

$(document).ready(function () {
     
                    $("#grid").kendoGrid({
                        dataSource: {
                          transport: {
                    				read: function(options){
                              var data = [
                                {
                                	include: true,
                                  Amount: 20
                                },
                                {
                                	include: true,
                                  Amount: 30
                                },
                                {
                                	include: false,
                                  Amount: 0
                                }
                              ];
                            	options.success(data);
                            }
                          },
                          schema:{
                            model: {
                              fields: {
                                include: { type: 'boolean' },
                                Amount: { type: "number", },
                              }
                            }
                          }
                        },
                        columns: [
                            { 
                              field: "include", 
                              editor: function(container, options){

                                var grid = $(container).closest('[data-role=grid]').data('kendoGrid');
                                var row = grid.dataItem(container.closest('tr'));

                                //console.log('grid', grid);
                                console.log('row', row);
                                if(row.include){
                                  row.set('include', false);
                                  row.set('Amount', 0);
                                } else {
                                	row.set('include', true);
                                  row.set('Amount', 1);
                                }

                                grid.closeCell();
                              },
                              template: function(items){
                                var guid = kendo.guid();
                                
                                var checked = ''; // = ' disabled="disabled" ';
                                if(items.include){
                                  checked = ' checked="checked" ';
                                }
                                return '<input class="k-checkbox" id="' + guid + '" type="checkbox" ' + checked + ' />' + 
                                  '<label class="k-checkbox-label" for="' + guid + '">&#8203;</label>';
                              },
                              attributes:{ align:"center" },
															headerAttributes: { 'class': 'k-header-centeralign' }
                            },
                          {
                            field: "Amount",
                            format: "{0:n6}",
                            editor: function(container, options){
                            	$('<input data-bind="value:' + options.field + '"/>')
                                .appendTo(container)
                                .kendoNumericTextBox({
                                  decimals: 6,
                                  min: 0,
                                  restrictDecimals: true // Specifies whether the decimals length should be restricted during typing. The length of the fraction is defined by the decimals value
                                }
                              );
                            }
                          }
                        ],
                        editable: true,
                      	save: function(e){
                      		console.log('save', e);
			
                          var model = e.model;
                          console.log('save model', model);

                          var items = this.dataSource.data();
                          var item = $.grep(items, function(e){ return e.uid == model.uid; })[0];
                          //console.log('item uid', items);

                          var userAmount = e.values.Amount;

                          if(userAmount>0){
                            item.set('include', true);
                            console.log('set include true');
                          } else {
                            item.set('include', false);
                            console.log('set include false');
                          }
                          
                          // redraw row for checkbox
                          // timeout because qty is not updated before
                          var grid = e.sender;
                          setTimeout(function(){
                            var row = grid.element.find('tr[data-uid=' + model.uid + ']');
                            console.log('redraw row for checkbox', row);
                            kendoFastReDrawRow(grid, row);
                          },0);
                          
                        },
                        dataBound: function(e){
                          console.log('dataBound');
                        },
                    });
                });

              
            function kendoFastReDrawRow(grid, row) {
	var dataItem = grid.dataItem(row);
	var rowChildren = $(row).children('td[role="gridcell"]');
	for (var i = 0; i < grid.columns.length; i++) {
		var column = grid.columns[i];
		var template = column.template;
		var cell = rowChildren.eq(i);
		if (template !== undefined) {
			var kendoTemplate = kendo.template(template);
			// Render using template
			cell.html(kendoTemplate(dataItem));
		} else {
			var fieldValue = dataItem[column.field];
			var format = column.format;
			var values = column.values;
			if (values !== undefined && values != null) {
				// use the text value mappings (for enums)
				for (var j = 0; j < values.length; j++) {
					var value = values[j];
					if (value.value == fieldValue) {
						cell.html(value.text);
						break;
					}
				}
			} else if (format !== undefined) {
				// use the format
				cell.html(kendo.format(format, fieldValue));
			} else {
				// Just dump the plain old value
				cell.html(fieldValue);
			}
		}
	}
}
td[role=gridcell] .k-checkbox + label.k-checkbox-label {
	cursor: pointer !important;
	
}
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2018.2.620/styles/kendo.common-bootstrap.min.css" />
    <link rel="stylesheet" href="https://kendo.cdn.telerik.com/2018.2.620/styles/kendo.bootstrap.min.css" />
    <link rel="stylesheet" href="https://kendo.cdn.telerik.com/2018.2.620/styles/kendo.bootstrap.mobile.min.css" />

    <script src="https://kendo.cdn.telerik.com/2018.2.620/js/jquery.min.js"></script>
    <script src="https://kendo.cdn.telerik.com/2018.2.620/js/kendo.all.min.js"></script>

<div id="example">
  <div id="grid"></div>
</div>