Getting error when filtering and sorting enums in dynamic datagrid example

Hi,

Thanks to the Radzen team for this amazing product, project and work. You rock! :mechanical_arm:

I'm trying to extend the Dynamic data example we can find in Radzen docs to see if it's possible to filter and sort by Enum field.

I know there's a dedicated page in the Radzen docs dedicated to Enum filtering, but regarding to dynamic page data, I've tried several configurations but always getting errors in the JS console when filtering or sorting by an Enum field.

To reproduce what I'm trying to explain, just go to the Dynamic data page and add this modified code to add an enum field in the datagrid.

@using System.Linq.Dynamic.Core

<RadzenDataGrid @bind-Value=@selectedItems Data="@data" TItem="IDictionary<string, object>" ColumnWidth="200px"
                        AllowFiltering="true" FilterPopupRenderMode="PopupRenderMode.OnDemand" FilterMode="FilterMode.Advanced" AllowPaging="true" AllowSorting="true">
        <Columns>
            @foreach(var column in columns)
            {
                <RadzenDataGridColumn @key=@column.Key Title="@column.Key" Type="column.Value"
                        Property="@GetColumnPropertyExpression(column.Key, column.Value)" >
                    <Template>
                        @context[@column.Key]
                    </Template>
                </RadzenDataGridColumn>
            }
    </Columns>
</RadzenDataGrid>

@code {
    IList<IDictionary<string, object>> selectedItems;

    public IEnumerable<IDictionary<string, object>> data { get; set; }

    public IDictionary<string, Type> columns { get; set; }

    public enum EnumTest {
        EnumValue1,
        EnumValue2
    }

    public string GetColumnPropertyExpression(string name, Type type)
    {
        var expression = $@"it[""{name}""].ToString()";

        if (type == typeof(int))
        {
            return $"int.Parse({expression})";
        }
        else if (type == typeof(DateTime))
        {
            return $"DateTime.Parse({expression})";
        }
        else if (type == typeof(EnumTest))
        {
            return $"(EnumTest)Enum.Parse(typeof(EnumTest), {expression})";
        }

        return expression;
    }

    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();

        columns = new Dictionary<string, Type>()
        {
            { "EmployeeID", typeof(int) },
            { "EnumTest", typeof(EnumTest) },
            { "FirstName", typeof(string) },
            { "LastName", typeof(string) },
            { "HireDate", typeof(DateTime) },
        };

        foreach (var i in Enumerable.Range(0, 50))
        {
            columns.Add($"Column{i}", typeof(string));
        }

        data = Enumerable.Range(0, 100).Select(i =>
        {
            var row = new Dictionary<string, object>();

            foreach (var column in columns)
            {
                row.Add(
                    column.Key, 
                    column.Value == typeof(EnumTest) 
                        ? (i % 2 == 0 ? EnumTest.EnumValue1 : EnumTest.EnumValue2)
                        : column.Value == typeof(int)
                            ? i 
                            : column.Value == typeof(DateTime) 
                                ? DateTime.Now.AddMonths(i) 
                                : $"{column.Key}{i}"
                );
            }

            return row;
        });
    }
}

When filtering or sorting you'll see JS console errors appear. Could anyone give more light on this topic? I don't know what else I could test.

Here you have a gif about this behavior.

dynamic-emum-filter (1)

Thanks for all help in advance!

Philippe

Actually using the latest version these expressions can be simplified to:

    public string GetColumnPropertyExpression(string name, Type type)
    {
        return $@"{type.Name}(it[""{name}""])";
    }

I'll update the demo!

I spoke to soon, unfortunately - it will be hard to provide generic expression that works in both sorting and filtering and especially if you have enums. Here is a modified version of your code that will work in all cases:

@using System.Linq.Dynamic.Core

<RadzenDataGrid @bind-Value=@selectedItems Data="@data" TItem="IDictionary<string, object>" ColumnWidth="200px"
                AllowFiltering="true" FilterPopupRenderMode="PopupRenderMode.OnDemand" FilterMode="FilterMode.Advanced" AllowPaging="true" AllowSorting="true">
    <Columns>
        @foreach (var column in columns)
        {
            <RadzenDataGridColumn @key=@column.Key Title="@column.Key" Type="column.Value"
                                  Property="@GetColumnPropertyExpression(column.Key, column.Value)">
                <Template>
                    @context[@column.Key]
                </Template>
            </RadzenDataGridColumn>
        }
    </Columns>
</RadzenDataGrid>

@code {
    IList<IDictionary<string, object>> selectedItems;

    public IEnumerable<IDictionary<string, object>> data { get; set; }

    public IDictionary<string, Type> columns { get; set; }

    public enum EnumTest
    {
        EnumValue1,
        EnumValue2
    }

    public string GetColumnPropertyExpression(string name, Type type)
    {
        var expression = $@"it[""{name}""].ToString()";

        if (type == typeof(int))
        {
            return $"int.Parse({expression})";
        }
        else if (type == typeof(DateTime))
        {
            return $"DateTime.Parse({expression})";
        }
        else if (type.IsEnum)
        {
            return $@"Int32(Enum.Parse(it[""{name}""].GetType(), {expression}))";
        }

        return expression;
    }

    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();

        columns = new Dictionary<string, Type>()
        {
            { "EmployeeID", typeof(int) },
            { "MyColumn", typeof(EnumTest) },
            { "FirstName", typeof(string) },
            { "LastName", typeof(string) },
            { "HireDate", typeof(DateTime) },
        };

        foreach (var i in Enumerable.Range(0, 50))
        {
            columns.Add($"Column{i}", typeof(string));
        }

        data = Enumerable.Range(0, 100).Select(i =>
        {
            var row = new Dictionary<string, object>();

            foreach (var column in columns)
            {
                row.Add(
                    column.Key,
                    column.Value == typeof(EnumTest)
                        ? (i % 2 == 0 ? EnumTest.EnumValue1 : EnumTest.EnumValue2)
                        : column.Value == typeof(int)
                            ? i
                            : column.Value == typeof(DateTime)
                                ? DateTime.Now.AddMonths(i)
                                : $"{column.Key}{i}"
                );
            }

            return row;
        });
    }
}

Also, avoid naming your columns after types.