MVC Grid Additional Checkbox columns

5 posts, 0 answers
  1. Bruce
    Bruce avatar
    14 posts
    Member since:
    Mar 2019

    Posted 13 May 2019 Link to this post

    Hi,

     

    I thought my scenario was pretty simple, and should be fairly easy to achieve, but it's turning out to be a bit more complex :(

     

    I have a list of invoices in a grid. Invoices have a capital amount and a fee amount.

    The user can select if the client wants to settle(pay) the capital amount, the fee amount, or both.

    When the user checks the capital and/or fee amount the settlement amount field is populated accordingly. All information required is in the underlying model data row.

    I figured I'd just add some booleans to my model, create some check box columns bound to the booleans, and create some javascript events on change or on click to just set the payment amount based on what was clicked.

    However, after much searching on this forum, it seems that I have to use client templates for the checkbox columns. Then when I tried that, I see they're all checked by default, the 'check binding' doesn't appear to work, and not sure exactly what events are fired and when. I can check the checkboxes before I enable inline editing, and when i do enable inline editing, the check box ticking doesn't fire any row changed events but if I click on the open space next to it, the field goes into edit mode then only.

    It just feels messy.

    I've searched the forums and it seems that there is no clean way to do this:   https://www.telerik.com/forums/how-to-have-more-than-one-checkbox-column

    I think with another few hours of messing around I can probably get this to work. But my question is:

    What is the RECOMMENDED way to get this done?

    I need additional checkbox columns. I need an event fired on changed or checked to update another field in the same row.

    I will handle posting to the server later on via a button as i need to capture payment dates and references and stuff.

    This is how far i got right now, checkboxes are ticked by default even though the model says false for those checkbox fields and the event is not firing at the right time, only at read which is wrong:

    @(
        Html.Kendo().Grid<emscredit.Models.Invoice>()
        .Name("active-invoices-" + batch.batch.Id)
        .Columns(columns =>
        {
            columns.Select().Title("Select All").Width(35);
            columns.Bound(c => c.InvoiceNo);
            columns.Bound(c => c.InvoiceAmount);
            columns.Bound(c => c.SettleCapitalAmount).ClientTemplate("<input type='checkbox' \\#= SettleCapitalAmount ? checked='checked' :'' \\# />");
            columns.Bound(c => c.SettleFeeAmount).ClientTemplate("<input type='checkbox' \\#= SettleFeeAmount ? checked='checked' :'' \\# />");
            columns.Bound(c => c.TotalSettlement);
        })
        .Editable(editable => editable.Mode(GridEditMode.InCell))
        .Pageable(pageable => pageable
            .Refresh(true)
            .PageSizes(true)
            .ButtonCount(5))
        .DataSource(dataSource => dataSource
            .Ajax()
            .Model(model => {
                model.Id(i => i.Id);
                model.Field(c => c.InvoiceNo).Editable(false);
                model.Field(c => c.InvoiceAmount).Editable(false);
            })
            .Read(read => read.Action("ReadActiveInvoices", "InvoiceGrid", new { batchId = batch.batch.Id }))
            .PageSize(20)
            .Events(events => events.Change("processReceiptsRowChanged()"))
        )
    )

     

    Thanks,

    Bruce

  2. Tsvetomir
    Admin
    Tsvetomir avatar
    693 posts

    Posted 15 May 2019 Link to this post

    Hi Bruce,

    Thank you for sharing such an extensive information on the scenario you are willing to achieve and the research you have conducted.

    Generally, when a boolean field is present along with the InCell edit mode, a slightly different approach has to be undertaken. Essentially, what I can recommend is to disable the checkbox from editing, rather edit the field programmatically. This would improve the overall UX of the application as well. As this would not allow for the cell to enter edit mode, thus, rendering a completely different checkbox. Refer to the following code snippets below for more information:

    1. Make a ClientTemplate and make the cell non editable:

    columns.Bound(x => x.IsStudent).Editable("returnFalse").ClientTemplate("<input type='checkbox' id='IsStudent_#=Id#' class='k-checkbox' #if(IsStudent){# checked #}#/><label for='IsStudent_#=Id#' class='k-checkbox-label k-no-text'></label>").Width(100);

    2. The Editable property accepts a JavaScript function name. Depending on the returned boolean value, the cell would be either editable or non-editable:

    function returnFalse(e) {
        return false;
    }

    3. Attach the click event handler to the check box and update the model's boolean field:

    .Events(ev=>ev.DataBound("onDataBound"))
     
    function onDataBound(e) {
        $("input[type='checkbox']").on("click", function (e) {
            var field = this.id.split('_')[0];
            debugger;
            var state = this.checked; // Depending on the state of the checkbox, you might set other fields via the set() method
            var dataItem = $("#grid").getKendoGrid().dataItem(e.target.closest("tr"));
     
            dataItem.set(field, state); // Use the same approach for other fields, you would like to modify 
                       // The syntax is as follows: dataItem.set("FieldName", value);
        });
    }

    4. You can update any other field of the model by following the approach above. Actually, you have the current data item, simply, update the field of interest with values according to your preferences. More information on the set() method could be found in the following article:

    https://docs.telerik.com/kendo-ui/api/javascript/data/observableobject/methods/set

    I am also attaching a sample project in which you can observe the suggestion above in action.

    Following the mechanics of the input with type "checkbox", whenever there is the checked attribute present, the checkbox will be checked. There is no way to set it to false. You either add the attribute or do not add it at all, if you would like to make it unchecked. 

    I have also noticed that you have escaped the "#" symbols. This would prevent the template from evaluating with the Kendo UI Grid. This approach is suggested, when there is nesting of templates and they have to be evaluated at different time. For instance, in the case of a hierarchy. 

    I hope you find those clarifications helpful. Let me know in case additional information is required.


    Kind regards,
    Tsvetomir
    Progress Telerik
    Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
  3. Bruce
    Bruce avatar
    14 posts
    Member since:
    Mar 2019

    Posted 15 May 2019 Link to this post

    Hi Tsvetomir,

    Thanks so much for replying. I'll give it a try.

    Thats a neat trick with the returnFalse btw

    Bruce

  4. Bruce
    Bruce avatar
    14 posts
    Member since:
    Mar 2019

    Posted 15 May 2019 in reply to Bruce Link to this post

    Yep, She works beautifully now!

    The Grid:

    @(
        Html.Kendo().Grid<emscredit.Models.Invoice>()
        .Name("active-invoices-" + batch.batch.Id)
        .Columns(columns =>
        {
            columns.Bound(c => c.InvoiceNo);
            columns.Bound(c => c.InvoiceAmount).Format("{0:c}");
            columns.Bound(c => c.SettleCapitalAmount).Editable("returnFalse").ClientTemplate("<input type='checkbox' id='SettleCapitalAmount_" + batch.batch.Id + "_#=Id#' class='k-checkbox' #if(SettleCapitalAmount){# checked #}#/><label for='SettleCapitalAmount_" + batch.batch.Id + "_#=Id#' class='k-checkbox-label k-no-text'></label>").Width(60);
            columns.Bound(c => c.SettleFeeAmount).Editable("returnFalse").ClientTemplate("<input type='checkbox' id='SettleFeeAmount_" + batch.batch.Id + "_#=Id#' class='k-checkbox' #if(SettleFeeAmount){# checked #}#/><label for='SettleFeeAmount_" + batch.batch.Id + "_#=Id#' class='k-checkbox-label k-no-text'></label>").Width(60);
            columns.Bound(c => c.TotalSettlement).Format("{0:c}");
        })
        .Events(ev => ev.DataBound("onActiveInvoicesDataBound"))
        .Pageable(pageable => pageable
            .Refresh(true)
            .PageSizes(true)
            .ButtonCount(5))
        .DataSource(dataSource => dataSource
            .Ajax()
            .Model(model => {
                model.Id(i => i.Id);
                model.Field(c => c.InvoiceNo).Editable(false);
                model.Field(c => c.InvoiceAmount).Editable(false);
            })
            .Read(read => read.Action("ReadActiveInvoices", "InvoiceGrid", new { batchId = batch.batch.Id }))
            .PageSize(20)
        )
    )

    Js:

    <script>
        function returnFalse(e) {
            return false;
        }
     
        function onActiveInvoicesDataBound(e) {
            $("input[type='checkbox']").on("click", function (e) {
                var thisIdAr = this.id.split('_');
                var field = thisIdAr[0];
                var batch = thisIdAr[1];
                //var dataItemId = thisIdAr[2];
     
                var state = this.checked; // Depending on the state of the checkbox, you might set other fields via the set() method
                var dataItem = $("#active-invoices-" + batch).getKendoGrid().dataItem(e.target.closest("tr"));
     
                if (typeof dataItem == "undefined")
                    return;
     
                dataItem.set(field, state); // Use the same approach for other fields, you would like to modify 
                                            // The syntax is as follows: .set("FieldName", value);
     
                setSettlementAmount(dataItem);
                updateActiveInvoicesSummary(batch);
            });
        }
     
        function setSettlementAmount(dataItem) {
            if (typeof dataItem == "undefined")
                return;
            var totalSettlement = 0;
     
            if (dataItem.SettleCapitalAmount)
                totalSettlement = totalSettlement + dataItem.get("DiscountAmountDispensed");
     
            if (dataItem.SettleFeeAmount)
                totalSettlement = totalSettlement + dataItem.get("EMSInvoiceAmount");
     
            dataItem.set("TotalSettlement", totalSettlement);
        }
     
        function updateActiveInvoicesSummary(batch) {
            //ToDo
        }
    </script>

     

    Thanks ;)

  5. Tsvetomir
    Admin
    Tsvetomir avatar
    693 posts

    Posted 17 May 2019 Link to this post

    Hi Bruce,

    I am glad to hear that I have been helpful in resolving the case on hand. And thank you for sharing your approach with the community.

    Generally, the approach with setting the checkbox column to be non-editable is recommended because in both - read and edit mode, a checkbox is present. However, those two checkboxes are two distinct elements which might confuse the user. That is why, the best way to go would be to manually update the field of the model (basically the equivalent of the Editor template). 

    Feel free to contact us in case you encounter any issues along the way.


    Kind regards,
    Tsvetomir
    Progress Telerik
    Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Back to Top