We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date

Is it possible to have a dropdown with checkboxes in a grid?

For example - selecting roles for a user. A single user can have several different roles attached. For selecting a single detail record, it works great to use a normal dropdown. but for a detail field that can have a one-to-many relationship with the "foriegn" datasource, it needs checkboxes or some other form of multi-select.

If so, what would the viewmodel need to look like for the main data source?

5 Replies

SS Seeni Sakthi Kumar Seeni Raj Syncfusion Team November 16, 2016 12:57 PM UTC

Hi Brian, 

We understand that you would like to use the checkbox selection the ForeignKey column’s dataSource. This can be achieved using the EditTemplate of the columns. Please refer to the following code example. 

@(Html.EJ().Grid<OrdersView>("Events") 
        .Datasource((IEnumerable<object>)ViewBag.dataSource) 
             . ..  
             .. . .  
        .Columns(col => 
        { 
            col.Field("OrderID").HeaderText("Order ID").IsPrimaryKey(true).Add(); 
            col.Field("CustomerID").HeaderText("Customer ID").Add(); 
            col.Field("EmployeeID").ForeignKeyField("EmployeeID") 
                .EditTemplate(a => {  
                    a.Create("create").Read("read").Write("write");  
                }) 
                .DataSource(ViewBag.dropData) 
                .ForeignKeyValue("Roles").HeaderText("Employee ID").Add(); 
            col.Field("Freight").HeaderText("Freight").Format("{0:C}").Add(); 
            col.Field("ShipCity").HeaderText("Ship City").Add(); 
        }) 
        .ClientSideEvents(eve => 
        { 
            eve.QueryCellInfo("queryCellInfo"); 
        }) 
) 
 
<script> 
 
    function create() { 
        return "<input>"; 
    } 
    function read(args) { 
        var dropObj = args.ejDropDownList("instance"); 
        var data = args.ejDropDownList("getSelectedValue"); 
        var val = ej.DataManager(dropObj.model.dataSource).executeLocal(new ej.Query().where("Roles", "equal", data.split(",")[0]))[0].EmployeeID 
        if (!data) 
            return {}; 
 
        return val; 
    } 
    function write(args) { 
        var val = ej.isNullOrUndefined(args.rowdata["EmployeeID"]) ? "" : args.rowdata["EmployeeID"]; 
        var datas = ej.DataManager(args.column[2].dataSource).executeLocal(new ej.Query().where("EmployeeID", "equal", val)); 
        var selIndex = []; 
        for (var s = 0; s < datas.length; s++) { 
            selIndex.push(args.column[2].dataSource.indexOf(datas[s])); 
        } 
        args.element.ejDropDownList({ 
            dataSource: args.column[2].dataSource, 
            fields: { text: "Roles" }, 
            showCheckbox: true, 
            width: "100%", 
            selectedItems: selIndex 
        }); 
    } 
 
    function queryCellInfo(args) { 
        if (args.column.field == "EmployeeID") { 
            var datas = ej.DataManager(args.column.dataSource).executeLocal(new ej.Query().where("EmployeeID", "equal", args.data.EmployeeID)) 
            var str = ""; 
            for (var s = 0; s < datas.length; s++) { 
                str = s == 0 ? str.concat(datas[s].Roles) : str.concat("," + datas[s].Roles) 
            } 
            $(args.cell).text(str); 
        } 
 
    } 
</script> 

In this queryCellInfo event has been used to concatenate the values that relates the multiple values for the single Value EmployeeID in the Grid’s main dataSource.  

We have prepared a sample that can be downloaded from the following location. 


If we misunderstood your query, please share the following information to achieve your requirement. 

1)      Grid’s main DataSource 
2)      DataSource bind to the column 
3)      If you are not interested in using the foreignkey column of the Grid, you can refer the following KB which illustrates the Checkbox with dropdownlist 


4)      If you provide the sample data structure, it will helpful for us to validate your requirement 

Regards, 
Seeni Sakthi Kumar S. 



RB R Brian Lindahl November 16, 2016 05:50 PM UTC

That gets me part way there, but not quite. Here's something close to my data structures:

[User]
int ID
int Name

[Roles]
int ID
int Name

[UserRoles]
int ID
int RoleID
int UserID

So the grid would be something like
UserID
Name
Roles
1
Fred
admin,manager
2
Wilma
manager,cashier

the roles column would be the dropdown, containing the [Roles] items, inclusing "admin", "manager", and "cashier"
i'm fine with a viewmodel like

[UserView]
ID
Name
Roles

where roles would be a string containing the list of selected role IDs - i.e., what's displayed for "admin,manager" would come back to c# in the viewmodel as "1,2"

thank you for your help. i'm really liking the Syncfusion controls, I'm just having trouble getting my understanding up to speed. :)


SS Seeni Sakthi Kumar Seeni Raj Syncfusion Team November 17, 2016 12:55 PM UTC

Hi Brian, 

As per your request, we have modified the sample that can be downloaded from the following location. 


Based on your suggestion, we bound the RolesID  column for the Grid with values “1,2” which is the list of the RolesID (1,2,3…) with the corresponding Roles (“Admin, Manager”). Refer to the following table structure. 

        private void BindDataSource() 
        { 
            //Column DataSource 
            emp.Add(new Roles(1, "Tester")); 
            emp.Add(new Roles(2, "Engineer")); 
                . . . 
                    . .  
            emp.Add(new Roles(9, "Build analyst")); 
            int code = 10000; 
            for (int i = 1; i <= 9; i++) 
            { 
                string str = i.ToString() +"," + (i + 1).ToString(); 
                //Main dataSource for Grid 
                Ord.Add(new Orders(code + 1, "ALFKI", i,str)); 
                code += 5; 
            } 
        } 

Here Ord will be bound to the Grid whereas the emp will be bind to the Column RoleID. To render these type of Relational strings with the string concatenation, you can use the queryCellInfo event. Based on the values of RoleID (“1,2”), corresponding values (Roles) will be retrieved from the column dataSource and place them in the cell. Refer to the following code example. 

@(Html.EJ().Grid<OrdersView>("Events") 
        .Datasource((IEnumerable<object>)ViewBag.dataSource) 
        .EditSettings(edit => { edit.AllowAdding().AllowDeleting().AllowEditing(); }) 
              . . 
        .Columns(col => 
        { 
            col.Field("OrderID").HeaderText("Order ID").IsPrimaryKey(true).Add(); 
              .. . 
                   . .  
            col.Field("RoleID") 
                .EditTemplate(a => 
                { 
                    a.Create("create").Read("read").Write("write"); 
                }) 
                .DataSource(ViewBag.dropData).HeaderText("Roles").Add(); 
        }) 
        .ClientSideEvents(eve => 
        { 
            eve.QueryCellInfo("queryCellInfo"); 
        }) 
) 
 
<script> 
 
    function queryCellInfo(args) { 
        if (args.column.field == "RoleID") { 
            var field = args.column.field, merge = false; preds = []; 
            var txt = args.data.RoleID.split(","); 
             
            //create a query    
            var predicate = new ej.Predicate(field, "equal", ej.parseInt(txt[0])); 
            for (var tx = 1; tx < txt.length; tx++) { 
                preds.push(new ej.Predicate(field, "equal", txt[tx])); 
                merge = true; 
            } 
            if (merge) { 
                preds.unshift(predicate); 
                predicate = ej.Predicate.or(preds); 
            } 
            //filter the dataSource 
            var datas = ej.DataManager(args.column.dataSource).executeLocal(new ej.Query().where(predicate)); 
            var str = ""; 
            for (var s = 0; s < datas.length; s++) { 
                str = s == 0 ? str.concat(datas[s].Role) : str.concat("," + datas[s].Role) 
            } 
            $(args.cell).text(str); 
        } 
    } 
</script> 

Likewise, we can handle this string concatenation for editing using the EditTemplate of the Grid columns. Refer to the following code example. 

@(Html.EJ().Grid<OrdersView>("Events") 
        .Datasource((IEnumerable<object>)ViewBag.dataSource) 
        .EditSettings(edit => { edit.AllowAdding().AllowDeleting().AllowEditing(); }) 
            . . .  
                . ..  
        .Columns(col => 
        { 
            col.Field("OrderID").HeaderText("Order ID").IsPrimaryKey(true).Add(); 
            col.Field("CustomerID").HeaderText("Customer ID").Add(); 
            col.Field("EmployeeID").HeaderText("Employee ID").Add(); 
            col.Field("RoleID") 
                .EditTemplate(a => 
                { 
                    a.Create("create").Read("read").Write("write"); 
                }) 
                .DataSource(ViewBag.dropData).HeaderText("Roles").Add(); 
            col.Field("Freight").HeaderText("Freight").Format("{0:C}").Add(); 
        }) 
                . . . 
) 
 
<script> 
 
    function create() { 
        return "<input>"; 
    } 
    function read(args) { 
        var data = args.ejDropDownList("getSelectedValue"); 
 
        if (!data) 
            return {}; 
 
        return data; 
    } 
    function write(args) { 
        var val = ej.isNullOrUndefined(args.rowdata["RoleID"]) ? "" : args.rowdata["RoleID"]; 
        args.element.ejDropDownList({ 
            dataSource: args.column[3].dataSource, 
            fields: { text: "Role", value: "RoleID" }, 
            showCheckbox: true, 
            width: "100%", 
            value: val 
        }); 
    } 
</script> 

Regards, 
Seeni Sakthi Kumar S. 



MH Mohammad Haneef February 18, 2021 08:02 AM UTC

This code works very fine. 

However when I export to excel I get an error "Message=edittemplate is not a valid value for EditingType."

It happens in this line  :    object value = serializer.Deserialize(serialize, type);  Below is the full code. 


private GridProperties ConvertGridObject(string gridProperty)
        {
            JavaScriptSerializer serializer = new JavaScriptSerializer();
            IEnumerable div = (IEnumerable)serializer.Deserialize(gridProperty, typeof(IEnumerable));
            GridProperties gridProp = new GridProperties();
            foreach (KeyValuePair ds in div)
            {
                var property = gridProp.GetType().GetProperty(ds.Key, BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);
                if (property != null)
                {

                       Type type = property.PropertyType;
                        string serialize = serializer.Serialize(ds.Value);
                        object value = serializer.Deserialize(serialize, type);
                        property.SetValue(gridProp, value, null);
                   
                    
                }
            }
            return gridProp;
        }



Can you please suggest what may be the issue.

Regards

Haneef


TS Thavasianand Sankaranarayanan Syncfusion Team February 19, 2021 10:29 AM UTC

Hi Mohammad Haneef, 
 
We are able to reproduce the issue from our end. To avoid this reported issue “edittemplate was not found” we need to remove the editType from the Grid model while exporting. 
 
In the below code example, we have removed the editType of columns in toolbarClick event of Grid. 
 
[Index.cshtml] 
 
@(Html.EJ().Grid<Object> 
        ("FlatGrid") 
        .Datasource((IEnumerable<object>)ViewBag.DataSource) 
        .EditSettings(edit => { edit.AllowAdding().AllowDeleting().AllowEditing(); }) 
        .ClientSideEvents(events => events.ToolbarClick("toolbarClickHandler")) 
    .ToolbarSettings(toolBar => toolBar.ShowToolbar().ToolbarItems(items => 
 
     { 
           
         . . . . 
 
         items.AddTool(ToolBarItems.ExcelExport); 
 
     })) 
    .Columns(col => 
    { 
        col.Field("OrderID").HeaderText("Order ID").IsPrimaryKey(true).Add(); 
        col.Field("EmployeeID").HeaderText("Employee ID").Add(); 
        col.Field("CustomerID").HeaderText("Customer ID").Add(); 
        col.Field("ShipPostalCode").HeaderText("Ship Postal Code").EditTemplate(a => { a.Create("create").Read("read").Write("write"); }).Add(); 
    }) 
 
    ) 
 
<script type="text/javascript"> 
 
    function toolbarClickHandler(args) { 
 
        if (args.itemName.indexOf("Excel Export") != -1) { 
            var edittemplatecolumn = this.model.columns.filter(function (e) { 
                return e.editType == "edittemplate" 
            }); 
            var Index = this.getColumnIndexByField(edittemplatecolumn[0].field); // Get the edit template column index here.  
            delete this.model.columns[Index].editType; // Delete the edittemplate model while exporting.  
        } 
    } 
</script> 
 
 
 
Refer the help document. 
 
 
Regards, 
Thavasianand S. 


Loader.
Up arrow icon