Grid editing and enum problems

Dear friends at Syncfusion,
I have encountered a behaviour when working with enums in Grid component, which I'm not able to solve.
I'm trying to follow this tutorial from knowledge base:
This is my enum:
public enum UserState
{
[EnumMember(Value = "Nový")]
NEW = 0,
[EnumMember(Value = "Ověřený")]
VARIFIED = 1,
[EnumMember(Value = "Skrytý")]
BLOCKED = 2,
}
This is my simplified class:
public class User
{
[Key]
public int UserID { get; set; }
[Required]
public bool IsActive { get; set; } = true;
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
public string CompanyName { get; set; }
public string Note { get; set; }
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
public UserState UserState { get; set; }
}
And this is my grid:
@Html.EJS().Grid("DataGridGuests").DataSource(dataManager =>
{
dataManager.Json(ViewBag.dataSourceGuests).InsertUrl("/Users/Insert").RemoveUrl("/Users/Remove").UpdateUrl("/Users/Update").Adaptor("RemoteSaveAdaptor");
}).AllowResizing(true).AllowTextWrap(true).AllowSorting().AllowFiltering().AllowExcelExport().Columns(col =>
{
col.Field("UserID").HeaderText("ID").IsPrimaryKey(true).IsIdentity(true).AllowFiltering(false).Visible(false).MinWidth("8").Add();
col.Field("FirstName").AutoFit(true).HeaderText("Jméno").ValidationRules(new { required = true }).Add();
col.Field("LastName").AutoFit(true).HeaderText("Přijmení").ValidationRules(new { required = true }).Add();
col.Field("CompanyName").AutoFit(true).HeaderText("Společnost").AllowFiltering(false).Add();
col.Field("UserState").HeaderText("UserState").AllowFiltering(true).EditType("dropdownedit").Add();
}).AllowPaging().PageSettings(page => page.PageCount(4).PageSize(20).PageSizes(true)).Toolbar(new List() {
"Search", "Add", "Edit", "Delete", "Update", "Cancel", "ExcelExport"
}).EditSettings(edit => { edit.AllowAdding(true).AllowEditing(true).AllowDeleting(true).Mode(Syncfusion.EJ2.Grids.EditMode.Normal); }).FilterSettings(filter => { filter.Type(Syncfusion.EJ2.Grids.FilterType.Excel); }).AllowSelection().SelectionSettings(select => select.Type(Syncfusion.EJ2.Grids.SelectionType.Single)).ToolbarClick("toolbarclick").Render()
This works just fine for reading and filtering alike.
However, when editing, the edit dialog only contains as many value as I have in the grid. See picture below.

I can still easily solve this by changing the column and taking advantage of the DropDownList componenet:
col.Field("UserState").HeaderText("UserState").AllowFiltering(true).Edit(new { @params = DropDownList }).EditType("dropdownedit").Add();
@{
var DropDownList = new Syncfusion.EJ2.DropDowns.DropDownList() { DataSource = ViewBag.UserStates, Query = "new ej.data.Query()", AllowFiltering = true, IgnoreAccent = true, Fields = new Syncfusion.EJ2.DropDowns.DropDownListFieldSettings() { Value = "value", Text = "text" } };
}
and rendering values for dropdown from controller.
However, when I update my line (also adding), I get just the number corresponding to the enum, not the EnumMember value.


This is my update method:
public ActionResult Update(User value)
{
if (ModelState.IsValid)
{
db.Entry(value).State = EntityState.Modified;
db.SaveChanges();
}
else
{
var errors = ModelState
.Where(x => x.Value.Errors.Count > 0)
.Select(x => new { x.Key, x.Value.Errors })
.ToArray();
foreach (var error in errors)
{
System.Diagnostics.Debug.WriteLine(error.Key + "///" + error.Errors.First().ErrorMessage);
}
}
return Json(value);
}
And when looking at the value just before returning it back to view, it looks fine to me.


I feel like I'm missing something very simple, could you perhaps point me to the right direction?
Any help would be greatly appreciated.
Petr

5 Replies

TS Thiyagu Subramani Syncfusion Team July 31, 2020 03:04 AM UTC

Hi Petr, 

Thanks for contacting Syncfusion forum. 

We have analyzed your reported code blocks at our end. In your code, when editing UserState filed you have used dropdown control and its dataSource as ViewBag.UserStates. SO, before proceed this we need to know dropdown’s dataSource server side code and if possible share issue reproducing sample. 

Please get back to us, if you need any further assistance. 

Regards, 
Thiyagu S 



PE Petr August 7, 2020 01:09 PM UTC

Dear Thiyagu,
I use simple function that gets for me just the value and text of enum member

 public static List<object> UserStates
        {
            get
            {
                var userStates = new List<object>();

                Type enumType = typeof(UserState);

                // I will get all values and iterate through them     
                var enumValues = enumType.GetEnumValues();
                foreach (UserState value in enumValues)
                {
                    MemberInfo memberInfo =
                        enumType.GetMember(value.ToString()).First();
                    var descriptionAttribute =
                        memberInfo.GetCustomAttribute<DescriptionAttribute>();
                    UserState eval2 = value;
                    int value1 = (int)eval2;
                    userStates.Add(new { value = value, text = descriptionAttribute.Description });
                }
                return userStates;
            }
        }

Please, check the appended project. Everything relevant is in UsersController and related views
No connection string is provided.

Thank you for your advice.

Petr 


Attachment: EnumDropDownInGrid_6440388e.zip


TS Thiyagu Subramani Syncfusion Team August 12, 2020 10:42 AM UTC

Hi Petr, 

Thanks for update. 

We checked the attached sample and we unable to run the attached sample due to the database issues. So, we have prepared an sample with your code blocks and we able to reproduce the mentioned behavior(I get just the number corresponding to the enum, not the EnumMember value) while updating the record. 

To achieved your requirement "I only get the number corresponding to the enum, not the EnumMember value" we suggest you to use the valueAccessor function. 

Using the value accessor function we mapped the DataSource dropdown value with updated UserState value. Based on this we returned the required enumMember value in that column. Using actionBegin event we have passed required value to server side in args.requestType as save.  

Please refer to the below code and sample link. 

 
@{ 
    var valueAccessor = "valueAccessorFn"; 
} 
<div> 
    @Html.EJS().Grid("Grid").DataSource(dataManager => 
    { 
        dataManager.Json(ViewBag.dataSource).InsertUrl("/Home/Insert").RemoveUrl("/Home/Delete").UpdateUrl("/Home/Update").Adaptor("RemoteSaveAdaptor"); 
}).EditSettings(e => { e.AllowAdding(true).AllowEditing(true).AllowDeleting(true); }).Columns(col => 
{ 
. . . . . .  
   col.Field("UserState").HeaderText("UserState").AllowFiltering(true).Width("150").ValueAccessor(valueAccessor).Edit(new { create = "create", read = "read", destroy = "destroy", write = "write" }).Add(); 
}).AllowPaging().AllowSorting(true).ActionBegin("Begin").Toolbar(new List<string>() { "Add", "Edit", "Delete", "Update", "Cancel" }).Render() 
 
</div> 
 
<script> 
     var elem; 
    var dObj; 
    var instance; 
    var flag = false; 
    var dropData = @Html.Raw(Json.Encode(ViewBag.UserStates)); 
    function Begin(args) { 
        if (args.requestType === 'save') { 
            flag = true; 
            var userState = dropData.filter(or => or.text == args.data.UserState) 
            args.data.UserState = userState[0].value;  // Send required UserState value to server side 
        }  
    } 
 
    function valueAccessorFn(field, data, column) { 
        if (flag) { 
            var userState = dropData.filter(or => or.value == data.UserState) 
            var value = userState[0].text;   
            flag = false; 
            return value;  // Returned required enumMember value 
        } 
        else { 
            return data.UserState; 
        } 
 
    } 
 
    function create(args) { 
        elem = document.createElement('input'); 
        return elem; 
    } 
    function write(args) { 
        dObj = new ej.dropdowns.DropDownList({ 
            dataSource: dropData, 
            query: new ej.data.Query(), 
            allowFiltering: true, 
            ignoreAccent: true, 
            fields: { Value: "value", Text: "text" } 
        }); 
        dObj.appendTo(elem); 
    } 
 
    function destroy() { 
        dObj.destroy(); 
    } 
    function read(args) { 
        return dObj.value; 
    } 
 
</script> 

     public static List<OrdersDetails> GetAllRecords() 
        { 
            List<OrdersDetails> order = new List<OrdersDetails>(); 
            int code = 10000; 
            for (int i = 1; i < 10; i++) 
            { 
                order.Add(new OrdersDetails(code + 1, "ALFKI", i + 0, 2.3 * i, false, new DateTime(1991, 05, 15), "Berlin", "Simons bistro", "Denmark", new DateTime(1996, 7, 16), "Kirchgasse 6", UserState.BLOCKED)); 
. . . . . . . . .  
                code += 5; 
            } 
            return order; 
        } 
 
        . . . . . . . . . 
 
        [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] 
        public UserState UserState { get; set; } 
    } 
 
    public enum UserState 
    { 
        [EnumMember(Value = "Nový")] 
        [Description("Nový")] 
         NEW = 0, 
        [EnumMember(Value = "Ověřený")] 
        [Description("Ověřený")] 
        VARIFIED = 1, 
        [EnumMember(Value = "Skrytý")] 
        [Description("Skrytý")] 
        BLOCKED = 2, 
    } 

Screenshot for server side: 
 
 

After update: 

 




If still facing the issue please reproduce the issue above sample and revert to us. 

Please get back to us, if you need any further assistance. 

Regards, 
Thiyagu S. 



PE Petr August 26, 2020 08:43 PM UTC

Dear Thiagu,
thanks you very much for so much help. 

However, this still does not fully accomplish what I need. 
Let's use the sample you've generously provided 

All the cells in the UserState column, as well as the values in filter(I'm using FilterType.Excel in my original example) should only be working with values provided either in  [EnumMember(Value = "xxx")] or [Description("xxx")], I don't really mind either one of those, but never want to see the actual enum member.
This was working fine in my previous example, however it does not anymore.




And I think this is pretty obvious, but the solution you've provided only works as long as I'm not performing any operations on the table, such as sorting. If I do, the value for enum will revert back to 1.

I've got to say this is all pretty complicated for relatively simple task.

I don't mean to impose, but this behavior should probably be treat as bug.

Thank you for all your help.
Petr


TS Thiyagu Subramani Syncfusion Team September 1, 2020 12:32 PM UTC

Hi Petr,  
   
Thanks for your update.  
   
Incident has been created to fulfill your requirements. So please follow up on the incident for further updates.  
   
Regards,  
Thiyagu S  


Loader.
Up arrow icon