Editable checkbox in Grid column

- I am using version 15.4.0.17
- The grid below is shown in a view, where the user can select 1 or more records thru a checkbox ina grid column.
@(Html.EJ().Grid<object>("ItemsGrid")
.Datasource((IEnumerable<object>) ViewBag.datasource)
.AllowPaging()
.SelectionType(SelectionType.Multiple)
.Columns(col =>
{
col.Field("selected").HeaderText("Sel").AllowEditing(true).EditType(EditingType.Boolean).TextAlign(TextAlign.Center).Width(50).Add();
col.Field("ModuleName").HeaderText("Module").IsPrimaryKey(true).TextAlign(TextAlign.Left).AllowTextWrap().Width("40%").Add();
col.Field("ModuleDescription").HeaderText("Description").TextAlign(TextAlign.Left).AllowTextWrap().Width("60%").Add();
col.Field("ModuleId").HeaderText("Id").IsPrimaryKey(true).Visible(false).Add();
})
.ClientSideEvents(eve => eve.RecordClick("RecordClick").RowSelecting("RowSelecting"))

This is the resulting grid:

I need toachieve the following:

1. column "sel" must be displayed as checkboxand the user must be able to toggle it at any time with just 1 click.

2. column "sel" is binded to model.selected

3. all other columns must remain not editable

4. value of the checkbox must always reflect the correspondingcurrent value from model.selected, so paging anywhere else and coming back will not make checks "disappear"

5. when a checkbox is clicked, a controller action will be called using Ajax, so that the model.selected field will be updated to the tableon the server side, within the action that will be called with Ajax. Ajax call will pass only the 'ModuleId' and 'selected' values.


So far I have been able to either:

1. toggle the checkbox directly and perform satisfactorily the Ajax call,

or

2. show the current 'selected' value grayed out, non editable,

Any help would be greatly appreciated.






10 Replies

VA Venkatesh Ayothi Raman Syncfusion Team December 5, 2017 07:01 AM UTC

Hi Jose, 
 
Thanks for using Syncfusion products. 
 
We went through your screenshot and code example that you have shared for us and found that you are tried to update the Grid when we change the checkbox value is checked or unchecked. If so, we have built-in support of checkbox selection property and its enabled by set type as checkbox in columns property.  
 
If set type checkbox then the corresponding column is always editable and remaining columns are non-editable state. As from your scenario, you want to send the editable value to server side and update the database using AJAX post when checked/unchecked the checkbox column. If so, we suggest you to use remoteSaveAdaptor feature.  
 
In remoteSaveAdaptor mechanism works, Sometimes you may need to perform all Grid Actions in client-side except the CRUD operations that should be interacted with server-side to persist data. So, that Grid actions such as paging,filtering,sorting and grouping are works in client side and CRUD operations interacted with server side to persist the database. It can be achieved in Grid by using remoteSaveAdaptor.  

Refer to the following code example and Help documentation, 
 
@(Html.EJ().Grid<OrdersView>("Grid") 
                    .Datasource(ds => ds.Json(ViewBag.datasource).UpdateURL("UrlUpdate").InsertURL("UrlInsert").RemoveURL("UrlDelete") 
                    .Adaptor(AdaptorType.RemoteSaveAdaptor)) 
                    .AllowPaging() 
                    . .  . 
                    .EditSettings(edit => { edit.AllowAdding().AllowDeleting().AllowEditing(); }) 
                    . .  . 
                    .Columns(col => 
                    { 
                   .   .   . 
col.Field("Verified").Type("checkbox").HeaderText("Verified").Width(100).Add(); 
                    }) 
) 
 
[Controller side] 
 
public ActionResult UrlUpdate(EditableOrder value) 
        { 
            OrderRepository.Update(value); 
            var data = OrderRepository.GetAllRecords(); 
            return Json(data, JsonRequestBehavior.AllowGet); 
        } 
        public ActionResult UrlInsert(EditableOrder value) 
        { 
            OrderRepository.Add(value); 
            var data = OrderRepository.GetAllRecords(); 
            return Json(data, JsonRequestBehavior.AllowGet); 
        } 
        public ActionResult UrlDelete(int key) 
        { 
            OrderRepository.Delete(key); 
            var data = OrderRepository.GetAllRecords(); 
            return Json(data, JsonRequestBehavior.AllowGet); 
        } 
 
Note: In remoteSaveAdaptor, we have performed the AJAX post in source side. So, UrlUpdate method called automatically when we checked/unchecked the values in checkbox column. 
 
Help documentation: 
 
 
We have also prepared a sample based on your convenience which can be download from following link, 
 
 
 
Please let us know if you have any further assistance on this. 
 
 
Regards, 
Venkatesh Ayothiraman. 
 



JM Jose Monzon replied to Venkatesh Ayothi Raman December 9, 2017 06:46 PM UTC

Hi Jose, 
 
Thanks for using Syncfusion products. 
 
We went through your screenshot and code example that you have shared for us and found that you are tried to update the Grid when we change the checkbox value is checked or unchecked. If so, we have built-in support of checkbox selection property and its enabled by set type as checkbox in columns property.  
 
If set type checkbox then the corresponding column is always editable and remaining columns are non-editable state. As from your scenario, you want to send the editable value to server side and update the database using AJAX post when checked/unchecked the checkbox column. If so, we suggest you to use remoteSaveAdaptor feature.  
 
In remoteSaveAdaptor mechanism works, Sometimes you may need to perform all Grid Actions in client-side except the CRUD operations that should be interacted with server-side to persist data. So, that Grid actions such as paging,filtering,sorting and grouping are works in client side and CRUD operations interacted with server side to persist the database. It can be achieved in Grid by using remoteSaveAdaptor.  

Refer to the following code example and Help documentation, 
 
@(Html.EJ().Grid<OrdersView>("Grid") 
                    .Datasource(ds => ds.Json(ViewBag.datasource).UpdateURL("UrlUpdate").InsertURL("UrlInsert").RemoveURL("UrlDelete") 
                    .Adaptor(AdaptorType.RemoteSaveAdaptor)) 
                    .AllowPaging() 
                    . .  . 
                    .EditSettings(edit => { edit.AllowAdding().AllowDeleting().AllowEditing(); }) 
                    . .  . 
                    .Columns(col => 
                    { 
                   .   .   . 
col.Field("Verified").Type("checkbox").HeaderText("Verified").Width(100).Add(); 
                    }) 
) 
 
[Controller side] 
 
public ActionResult UrlUpdate(EditableOrder value) 
        { 
            OrderRepository.Update(value); 
            var data = OrderRepository.GetAllRecords(); 
            return Json(data, JsonRequestBehavior.AllowGet); 
        } 
        public ActionResult UrlInsert(EditableOrder value) 
        { 
            OrderRepository.Add(value); 
            var data = OrderRepository.GetAllRecords(); 
            return Json(data, JsonRequestBehavior.AllowGet); 
        } 
        public ActionResult UrlDelete(int key) 
        { 
            OrderRepository.Delete(key); 
            var data = OrderRepository.GetAllRecords(); 
            return Json(data, JsonRequestBehavior.AllowGet); 
        } 
 
Note: In remoteSaveAdaptor, we have performed the AJAX post in source side. So, UrlUpdate method called automatically when we checked/unchecked the values in checkbox column. 
 
Help documentation: 
 
 
We have also prepared a sample based on your convenience which can be download from following link, 
 
 
 
Please let us know if you have any further assistance on this. 
 
 
Regards, 
Venkatesh Ayothiraman. 
 


Thanks for your reply.  The remoteSaveAdaptor seems great but Ajax is a must because I need to handle some specific Ajax functionalities, like sending specific properties along with the AntiForgeryToken.

 Your example gave me the idea of using ActionBegin:

.ClientSideEvents(eve => eve.ActionBegin("save"))

 

And then:

function save(args) {

                        if (args.requestType == "save"&& flag) {

                            flag = true;

                            var record = args.data;

                            args.cancel = true;

                            var form = $('#__AjaxAntiForgeryForm');

                            var tkn = $('input[name="__RequestVerificationToken"]', form).val();

                            var projectId = '@ViewBag.projectId';

                            var checked = record.selected; //send ajax post

                            $.ajax({

                                type: "POST",

                                url: "toggleCheck",

                                content: "application/json; charset=utf-8",

                                dataType: "json",

                                data: {

                                    __RequestVerificationToken: tkn,

                                    projectId: projectId,

                                    moduleId: args.data.ModuleId,

                                    sel: checked

                                },

                                onreadystatechange: function(resp) {

                                    if (resp.readyState === 4 && resp.status === 200) {

                                        successCallback(resp);

                                    }

                                },

                                success: function(d) {...

                                }

                            });

                        }

                    }

FYI, the controller-action called thru Ajax, besides using AntiForgeryToken, just saves the 'selected' bool value to it's table.

So far it's working great, any other suggestions you might have are welcomed.

I'll let you know if anything else arises. Thanks.

 



VA Venkatesh Ayothi Raman Syncfusion Team December 11, 2017 06:55 AM UTC

Hi Jose, 

Thanks for the update. 

As from your query, do you want to send the Antiforgerytoken for authentication purpose while perform the CRUD operation in Grid? If so, We have created a sample based on your requirement using AntiForgeryToken. While using AntiForgeryToken to editing we need to use AntiForgeryToken() html method in edit form. Because Antiforgery token validate the inside form element,  we suggest you to use template editing to grid.

Please refer to the code example and sample, 
<Script> 
var dmAdaptorUpdate = function (keyField, value, tableName) { 
 
        var res = this.adaptor.update(this, keyField, value, tableName); 
        return $.ajax($.extend({ 
            beforeSend: ej.proxy(this._beforeSend, this) 
        }, res)); 
    } 
 
    var dmAdaptorInsert = function (data, tableName) { 
        var res = this.adaptor.insert(this, data, tableName); 
        var deffer = $.Deferred(); 
        $.ajax($.extend({ 
            beforeSend: ej.proxy(this._beforeSend, this), 
            success: ej.proxy(function (record, status, xhr, request) { 
                record = function () { 
                    if (data.d) 
                        data = data.d; 
                    return data; 
                }; 
                deffer.resolveWith(this, [{ record: record, dataManager: this }]); 
            }, this), 
            error: function (e) { 
                deffer.rejectWith(this, [{ error: e, dataManager: this }]); 
            } 
        }, res)); 
 
        return deffer.promise(); 
    }  
 
    var adaptor = new ej.remoteSaveAdaptor ().extend({ 
        update: function (dm, keyField, value, tableName) { 
            var token = value.__RequestVerificationToken; 
            delete value['__RequestVerificationToken']; 
            return { 
                type: "POST", 
                url: dm.dataSource.updateUrl || dm.dataSource.crudUrl || dm.dataSource.url, 
                data: { 
                    __RequestVerificationToken: token, 
                    value: value 
                } 
            }; 
        }, 
        insert: function (dm, data, tableName) { 
            var token = data.__RequestVerificationToken; 
            delete data['__RequestVerificationToken']; 
            return { 
                type: "POST", 
                url: dm.dataSource.insertUrl || dm.dataSource.crudUrl || dm.dataSource.url, 
                data: { 
                    __RequestVerificationToken: token, 
                    value: data 
                } 
            }; 
        }, 
         
         
    }) 
 
    function load(args) { 
        this.model.dataSource.adaptor = new adaptor(); 
 
        this.model.dataSource.update = dmAdaptorUpdate; 
        this.model.dataSource.insert = dmAdaptorInsert; 
            } 
    </script> 
 
 

We have rendered the dialog template while editing or creating a record. Please refer to the below code example,

 
@(Html.EJ().Grid<EJGrid.Models.EmployeeView>("Editing") 
        .Datasource(ds => ds.Json((IEnumerable<object>)ViewBag.datasource).Adaptor("remoteSaveAdaptor").UpdateURL("/Home/Update").InsertURL("/Home/Insert").RemoveURL("/Home/Remove")) 
            .EditSettings(edit =>edit.AllowAdding().AllowDeleting().AllowEditing().EditMode(EditMode.DialogTemplate).DialogEditorTemplateID("#template")) 
        ………….. 
        }) 
  .ClientSideEvents(eve => eve.Load("load").ActionBegin("actionBegin")) 
 
) 
 
<script type="text/template" id="template"> 
    <b>Order Details</b> 
    @Html.AntiForgeryToken() 
    <table cellspacing="10"> 
        <tr> 
. .   
        </tr> 
    </table> 
</script> 
 
 
 [Controller] 
        [HttpPost] 
        [ValidateAntiForgeryToken] 
        public ActionResult Update(EmployeeView value) 
        { 
            OrderRepository.Update(value); 
            var data = OrderRepository.GetAllRecords2(); 
            return Json(value, JsonRequestBehavior.AllowGet); 
        } 
        [ValidateAntiForgeryToken] 
        public ActionResult Insert(EmployeeView value) 
        { 
            OrderRepository.Add(value); 
            var data = OrderRepository.GetAllRecords2(); 
            return Json(data, JsonRequestBehavior.AllowGet);
        }
 
 

In the above sample we have extend the adaptor to include the AntiForgeryToken key before send post to server side.

Refer to the online help documentation for custom adaptor for adaptor extend,

Document: http://help.syncfusion.com/js/datamanager/data-adaptors#custom-adaptor 

Regards, 
Venkatesh Ayothiraman. 



JM Jose Monzon December 19, 2017 03:39 AM UTC

Hi. Your suggestion goes a step further than my original requirement and I will use it to help me improve another Ajax assisted CRUD views for which I still have not yet implemented the Antiforgerytoken.

Thanks very much for your help, I do really appreciate it.


JM Jose Monzon December 19, 2017 04:40 AM UTC

One other thing, specifically for the mvc TreeGrid version 15.4.0.17 control, how can I customize the contents of the Delete confirmation dialog?  I tried using the sample for the Grid but seems it doesn't work with the TreeGrid


SR Suriyaprasanth Ravikumar Syncfusion Team December 20, 2017 11:07 AM UTC

Hi Jose, 
 
In TreeGrid, we can able to customize only the text content of the delete confirmation dialog by changing the locale text of “deleteRecordText” property. But we can’t able to customize the UI of the delete confirmation dialog. Can you please share your exact requirement of customizing the delete confirmation dialog. 
 
Please refer the below code snippet, to change the text content of the delete confirmation dialog. 
[HTML]  
<body> 
    <script type="text/javascript"> 
 
        $(function () { 
            $("#TreeGridContainer").ejTreeGrid({ 
                //.. 
           }) 
        }); 
        ej.TreeGrid.Locale["en-US"] = { 
            deleteRecordText: "Custom Text", 
        } 
    </script> 
</body> 

We have also prepared a sample for your reference, Please find the sample from the below link. 
 
Please let us know if you require any other assistance on this.   
 
Regards,   
Suriyaprasanth R.  



JM Jose Monzon December 21, 2017 02:54 PM UTC

Thanks for your reply. Regarding de delete confirmation dialog, I do need to customize its content because of 3 reasons:
1. Standarization, I like to keep away of using too many 3rd party libraries.
2. Make dialogs as informative as possible, because I've had users say "I thought..." and they only hit "delete" and disaster happens.
3. Multilanguage support, so dialogs have to be displayed in many languages.

I think for now I will keep using a bootstrap modal dialog with ok-cancel buttons, and wait for when the content of the treegrid delete confirmation can be customized.

Thank you very much for your support.


SR Suriyaprasanth Ravikumar Syncfusion Team December 22, 2017 06:58 AM UTC

Hi Jose, 

While analyzing your query and response, we have  planned to suggest you an another solution to achieve your requirement. Please find the response below. 

Query1: Standarization, I like to keep away of using too many 3rd party libraries. 
Query2: I will keep using a bootstrap modal dialog with ok-cancel buttons.         
Answer: In TreeGrid, using the ‘create’ client side event you can able to customize the delete confirmation dialog and you can replace the default dialog with your own custom modal popup. In the ‘create’ event you can able to get the dialog element attached to the DOM, you can customize this element without removing the ‘OK’ and ‘Cancel’ buttons to ensure the behavior.  
Please refer the code snippet below. 
 
[HTML] 
$(function () { 
            $(function () { 
                $("#TreeGridContainer").ejTreeGrid({ 
                    //.. 
                    // Event which get trigger after TreeGrid get rendered. 
                    create: function (args) { 
                        var confirmDialogDiv = $("#"+this._id+"_ConfirmDialog"); // Delete Condirmation dialog Div element 
                        confirmDialogDiv.find("input:eq(0)").css("background-color","red"); // Customize the UI element as per your preferance without removing it. 
                    }, 
            }); 
            ej.TreeGrid.Locale["en-US"] = { 
                deleteRecordText: "Custom Text", 
            } 


Please find the sample from the below link. 

Query3: Multilanguage support, so dialogs have to be displayed in many languages. 
Answer: In TreeGrid, we already have support to multiple locales and text in the delete confirmation can be customized to the specific locale as per your preference, by using “Locale” Property. 
Please refer the below link to know more about Locale property. 

Please let us know if you require any other assistance on this.   
 
Regards,   
Suriyaprasanth R.  



JM Jose Monzon December 22, 2017 12:29 PM UTC

Hi.  Thanks again for your reply.  I am to blame for not explaining myself better.

What I meant by customizing the delete dialog (and this somewhat applies to my "multilanguage support" issue too), is that I need the content to be dynamic too, that is, I need to display in the dialog properties from the current record that is about to be deleted.  

Such information to be displayed changes for every record and includes "specific properties" of the record about to be deleted.

If I'm not mistaken, the create event is fired only once: when the TreeGrid is rendered.  This means I won't be able of "refreshing" the content of the delete dialog with such "specific properties" after the TreeGird has been rendered, as I move from one record to another.

All of this could be solved by calling the Delete action method and refreshing the entire view. This is impractical.

It would be great if you can suggest me a way of refreshing the content of the delete dialog with specific properties of the record about to be deleted.  Otherwise, I will gladly wait for when this can be done.




SR Suriyaprasanth Ravikumar Syncfusion Team December 26, 2017 10:49 AM UTC


Hi Jose, 
 
We have achieved your requirement using “toolbarClick” client side event, which will be triggered on clicking any toolbar item. We have prepared a workaround sample by changing the text content of delete confirmation dialog based on the record which is to be deleted(selected record). Please refer the code snippet below. 
 
[HTML]   
    <script type="text/javascript"> 
 
    $(function () { 
         
        $("#TreeGridContainer").ejTreeGrid({ 
             
            //.. 
 
            toolbarClick: function (args) { 
                if (args.itemName == "Delete") { 
                    $("#TreeGridContainer_ConfirmDialog").find(".e-content").text("Are you sure want to delete the TaskId = " + args.model.selectedItem.taskID); //Enter the text content or append the requirement element as per your preference. The “model.selectedItem” contains the selected record details. 
                } 
            }, 
            toolbarSettings: { 
                showToolbar: true, 
                toolbarItems: [ 
                ej.TreeGrid.ToolbarItems.Delete, 
                ] 
            }, 
        }); 
 
    }); 
    </script> 
 
 
Please find the sample from the below link.  
 
Please let us know if you require any other assistance on this.    
  
Regards,    
Suriyaprasanth R.   


Loader.
Up arrow icon