How to create a seemless checkbox experience with boolean data type, batch editing in MVC core grid

1 Answer 793 Views
Checkbox Grid
Richard
Top achievements
Rank 1
Richard asked on 03 Nov 2021, 03:48 PM

Good afternoon 

If we look at the following demo page, we see Discontinued as a bool

https://demos.telerik.com/aspnet-mvc/grid/editing

Now I understand we can change the bound column to use a ClientTemplate to change true/false to a checkbox like so:

columns.Bound(p => p.Discontinued).ClientTemplate(
              "<input type='checkbox' value='#= Bin_ID #' " +
                 "# if (SiteHasBin) { #" +
                     "checked='checked'" +
                 "# } #" +
              "/>").Width(100);

What I am struggling with is how we go about removing the "click once to enter edit mode, click again to uncheck/check the checkbox before clicking save"

How do I go about effectively removing/hacking the existing code so that if a user sees a checkbox, they just click the checkbox AND the batch editing works out the box?

 


1 Answer, 1 is accepted

Sort by
0
Aleksandar
Telerik team
answered on 08 Nov 2021, 08:30 AM

Hi Richard,

You can achieve the desired result and we have several knowledgebase articles demonstrating how to achieve this using Kendo UI, here and here, for example. Below is the approach you can follow to implement the same for a Telerik UI for ASP.NET Core Grid and here is a runnable REPL example of the implementation:

  1. Add a ClientTemplate to render the checkbox and it's state based on the value of the dataItem field:
    .ClientTemplate("<input type='checkbox' #= Discontinued ? checked='checked' : '' # class='k-checkbox' />")
  2. Add the Editable configuration and a handler that would return false, to prevent entering the Edit mode
    .Editable("returnFalse");
    
    <script>
    function returnFalse(){
                return false;
            }
    </script>
  3. Add a handler to change event of the input, used to generate a checkbox and update the state:
    $("#grid .k-grid-content").on("change", "input.k-checkbox", function(e) {
                var grid = $("#grid").data("kendoGrid"),
                dataItem = grid.dataItem($(e.target).closest("tr"));
                // add the dirty flag to the cell
                $(e.target).closest("td").addClass("k-dirty-cell").prepend("<span class='k-dirty'></span>");
    
                // use equals, not the set() method because set will trigger the change event of the data source and the grid will rebind
                dataItem.Discontinued = this.checked;
    
                // mark the item as dirty so it will be added to the next update request
                dataItem.dirty = true;
            });

Here is the complete definition

@(Html.Kendo().Grid<Kendo.Mvc.Examples.Models.ProductViewModel>()
    .Name("grid")
    .Columns(columns => {
        columns.Bound(p => p.ProductName);
        columns.Bound(p => p.UnitPrice).Width(140);
        columns.Bound(p => p.UnitsInStock).Width(140);
        columns.Bound(p => p.Discontinued).Width(100)
            .ClientTemplate("<input type='checkbox' #= Discontinued ? checked='checked' : '' # class='k-checkbox' />")
            .Editable("returnFalse");
        columns.Command(command => command.Destroy()).Width(150);
    })
    .ToolBar(toolbar => {
        toolbar.Create();
        toolbar.Save();
    })
    .Editable(editable => editable.Mode(GridEditMode.InCell))
    .Pageable()
    .Navigatable()
    .Sortable()
    .Scrollable()
    .Events(events => events.Sort("onSort"))
    .DataSource(dataSource => dataSource
        .Ajax()
        .Batch(true)
        .PageSize(20)
        .ServerOperation(false)
        .Events(events => events.Error("error_handler"))
        .Model(model => model.Id(p => p.ProductID))
        .Create("Editing_Create", "Grid")
        .Read("Editing_Read", "Grid")
        .Update("Editing_Update", "Grid")
        .Destroy("Editing_Destroy", "Grid")
    )
)
<script type="text/javascript">
        function returnFalse(){
            return false;
        }

        $("#grid .k-grid-content").on("change", "input.k-checkbox", function(e) {
            var grid = $("#grid").data("kendoGrid"),
            dataItem = grid.dataItem($(e.target).closest("tr"));
            // add the dirty flag to the cell
            $(e.target).closest("td").addClass("k-dirty-cell").prepend("<span class='k-dirty'></span>");

            // use equals, not the set() method because set will trigger the change event of the data source and the grid will rebind
            dataItem.Discontinued = this.checked;

            // mark the item as dirty so it will be added to the next update request
            dataItem.dirty = true;
        });
        function error_handler(e) {
            if (e.errors) {
                var message = "Errors:\n";
                $.each(e.errors, function (key, value) {
                    if ('errors' in value) {
                        $.each(value.errors, function() {
                            message += this + "\n";
                        });
                    }
                });
                alert(message);
            }
        }

        // Prevent sorting when new record without Product Name is added
        function onSort(e) {
            var gridData = e.sender.dataSource.data()
            gridData.forEach(function (element) {
                if (!element.ProductName) {
                    e.preventDefault()
                }
            });
        }
    </script>

 

Regards,
Aleksandar
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

Richard
Top achievements
Rank 1
commented on 08 Nov 2021, 10:53 AM

Good morning Aleksander

I had followed the KB articles your example almost identically for my grid but I was still not getting the desired effect. In fact, it wasn't working at all.

So after a bit of investigation, I found the issue: the change event on the input.k-class wasn't firing.

I changed this:

$("#grid .k-grid-content").on("change",

to this:

$("#grid").on("change").on("change", 

I'm not sure why the .k-grid-content wasn't being flagged as such but at least I've got it working.

Marcus
Top achievements
Rank 1
commented on 04 Aug 2022, 08:58 AM | edited

Thank you so much for this hint @Richard!

I've been having the same issue with a checkbox column in a grid, where clicking the checkbox would not fire the change event. Your comment was exactly what I needed! (but actually, I only needed a single .on("change" :

$("#grid").on("change",

 

Best regards, Marcus

Tags
Checkbox Grid
Asked by
Richard
Top achievements
Rank 1
Answers by
Aleksandar
Telerik team
Share this question
or