Unable to filter by enum

Hi there,

I am unable to filter by enum.  When I click the filter icon for the enum column only the operator is visible in the popup but no place to "enter the value". See attached Image. (using v 26.1.35)

Screenshot from 2024-06-15 21-28-13.png


8 Replies

MS Monisha Saravanan Syncfusion Team June 17, 2024 06:22 AM UTC


Hi Wuss Wuzz,


Greetings from Syncfusion.


To perform Enum column filtering we suggest you to handle the filter externally using FilterTemplate feature of DataGrid. We have already documented this topic in the below UG section. Also, we have prepared a simple sample to perform filtering in Enum column using Menu Filter. Kindly check the below attached sample and code snippet for your reference.


Reference: https://blazor.syncfusion.com/documentation/datagrid/filtering#filter-enum-column


Sample: https://blazorplayground.syncfusion.com/embed/BNrTXRsQLhFJtzfK?appbar=true&editor=true&result=true&errorlist=true&theme=bootstrap5


<GridColumn Field=@nameof(Order.Orderingweekday) HeaderText="Day" Width="170" Type="ColumnType.String" HeaderTextAlign="TextAlign.Left" TextAlign="TextAlign.Left" >

 

         <FilterTemplate>

             @{

                 var data = context as PredicateModel<DayTypes>;

                 var a = data;

                     

             <SfDropDownList Placeholder="Orderingweekday" ID="Orderingweekday" @bind-Value="@data.Value" DataSource="@(DropDownDayTypes)" TValue="DayTypes" TItem="string">

 

                 <DropDownListFieldSettings Value="Orderingweekday" Text="Orderingweekday"></DropDownListFieldSettings>

                     <DropDownListEvents TItem="string" ValueChange="Change" TValue="DayTypes"></DropDownListEvents>

             </SfDropDownList>

             }

 

         </FilterTemplate>

              

 

     </GridColumn>


Please let us know if you have any concerns.


Regards,

Monisha




WW Wuss Wuzz June 17, 2024 01:54 PM UTC

I think i understand why I am having issues.

The sample presented
https://blazorplayground.syncfusion.com/embed/BNrTXRsQLhFJtzfK?appbar=true&editor=true&result=true&errorlist=true&theme=bootstrap5
Operators is defined but never used.

 SfDropDownList<DayTypes, string> DropDownDayTypesList; <--- defined but never used

"a = data" what is that for?
"public async Task Change(ChangeEventArgs<string, Data> args)" bears no resemblance to the documentation:
https://blazor.syncfusion.com/documentation/datagrid/filtering?cs-save-lang=1&cs-lang=razor
"Type" is used liberally and for different things, so it is hard to follow what is going on here.

 "public async Task Change(ChangeEventArgs<DayTypes, string> args)"  <-- this is different to the form used in the documentation above. It's not consistent

Finally I decided to copy your sample verbatim into the project and was extremely surprised that it does not work. The grid loads with the data but the filters do not open like they do on your hosted sample.  Are you sure that in your sample the code on the left is actually what is being displayed on the right?






WW Wuss Wuzz June 17, 2024 09:57 PM UTC

After some fiddling around I have this half working.

Query being sent is like

?$inlinecount=allpages&$filter=(startswith(MyEnum,'ENUM_STRING_VALUE'))&$skip=0&$top=20

but the enum is an interger not a string and being stored in the the DB as an integer.  So filtering will not work for me.  

  1. Where would I tell syncfusion grid it needs to send the numeric form of the enum and not its string value.
  2. Why is it using startswith instead of eq? It's an enum.
  3. Why is there an operator dropdown for an enum. The only valid operator should be equal I think?

Update: I worked around 2 & 3 by customizing the operator dialog using https://blazor.syncfusion.com/documentation/datagrid/filter-menu#customizing-filter-menu-operators-list  so quite happy about that outcome.


Only #1 outstanding.



PS Prathap Senthil Syncfusion Team June 18, 2024 10:13 AM UTC

Hi Wuss,


Based on your requirement, we suspect that you want to get the integer value of an enum. If so, you can use the following method to get the integer value of an enum. Kindly refer to the code snippet and sample below for your reference,


public async Task Change(ChangeEventArgs<DayTypes, string> args)

{

     FilterVal = args.Value.ToString();

     int dayValue = (int)Enum.Parse(typeof(DayTypes), FilterVal);  //here you can get value

 

     Console.WriteLine($"{FilterVal} is {dayValue}");

 

}


Sample: https://blazorplayground.syncfusion.com/embed/hjVTtxMPgosJNtLp?appbar=true&editor=true&result=true&errorlist=true&theme=bootstrap5

If you still face any issues or if we have misunderstood your query, we kindly request that you provide us with additional details to assist you further.  

  • Could you please share an issue-reproducible sample.
  • If possible, kindly share with us your attempts to reproduce the reported issue on the above-mentioned sample.

Thank you for your cooperation, and we will do our best to resolve this issue for you as soon as possible.


Regards,
Prathap Senthil



WW Wuss Wuzz June 18, 2024 08:04 PM UTC

Yes I know how to get an int out of an enum.  My question is
Where would I tell syncfusion grid it needs to send the numeric form of the enum and not its string value (in the filter request.

Git Repo Repro: https://github.com/janusqa/blazorbugs-syncfusion-enum

The enum is stored in the database as an Int.

class MyModel {
  MyEnum TheEnum {get; set;}
}

When EF creates the db field it creates it as an integer in the db.

The samples and documentation are sending the filter request with the enum as a string.  So filtering will never work as you cannot compare a string to an integer and expect to get a result. The page below sends a filter like

 Sending HTTP request GET https://localhost:7032/api/v1/notifications/odata?$inlinecount=allpages&$filter=(Level%20eq%20'SUCCESS')&$skip=0&$top=20

Do you see the 'SUCCESS'?  That's the enum.  It is incorrect.  It is sending the ENUM as a string value instead of an integer.  EF has stored the ENUM as an integer in the DB.  So when filtering it will try to compare 'SUCCESS' to 2. As you can see this will not work.  How should I fix it.
You should be able to copy the below code into a project that has HttpClient configured in Program.cs

As I've discussed about your sample, This page below is based on your sample after I cleaned it up.  You have variables and methods scattered throughout your sample that are not being used and it is hard to follow if they are necessary or not.  You should clean up your sample from having unnecessary code if it is not being used.

Here is the full sample of the page

@page "/enumsnotworking-1"
@rendermode @(new InteractiveServerRenderMode(prerender: false))


@using Syncfusion.Blazor.Grids
@using Syncfusion.Blazor.Data
@using Syncfusion.Blazor.DropDowns


@inject IHttpClientFactory _hc


<SfGrid @ref="sfGridRef" TValue="NotificationDto" AllowPaging="true" AllowFiltering="true" AllowSorting="true"
    Toolbar="@(new List<string>() { "Cancel", "Update" })">
    <SfDataManager Url=@($"api/{SD.ApiVersion}/notifications/odata") Adaptor="Syncfusion.Blazor.Adaptors.WebApiAdaptor"
        HttpClientInstance=@(_hc.CreateClient("App"))>
    </SfDataManager>
    <GridFilterSettings Type="Syncfusion.Blazor.Grids.FilterType.Menu" />
    <GridPageSettings PageSize="@SD.paginationDefaultSize" PageCount="5" PageSizes="true" />
    <GridEditSettings AllowEditing="true" AllowDeleting="true" ShowDeleteConfirmDialog="true" Mode="EditMode.Normal" />
    <GridEvents FilterDialogOpening="FilterDialogOpeningHandler" TValue="NotificationDto" />
    <GridColumns>
        <GridColumn Field=@nameof(NotificationDto.Id) HeaderText="Id" IsIdentity="true" IsPrimaryKey="true"
            Visible="false" />
        <GridColumn Field=@nameof(NotificationDto.Level) HeaderText="Level" AllowEditing="false">
            <FilterTemplate>
                @{
                    var data = context as PredicateModel<NotificationType>;
                    if (data is not null)
                    {
                        <SfDropDownList Placeholder="Level" DataSource="LevelDropDownSource" TValue="NotificationType"
                            TItem="string" @bind-Value="@data.Value">
                            <DropDownListFieldSettings Text="Level" Value="Level" />
                        </SfDropDownList>
                    }
                }
            </FilterTemplate>
        </GridColumn>
    </GridColumns>
</SfGrid>


@code {
    // syncfuscion
    private SfGrid<NotificationDto>? sfGridRef;


    private List<string> LevelDropDownSource = Enum.GetNames(typeof(NotificationType)).ToList();


    private void FilterDialogOpeningHandler(FilterDialogOpeningEventArgs args)
    {
        if (args.ColumnName == nameof(NotificationDto.Level))
        {
            args.FilterOperators = [new Operators() { Value = "equal", Text = "Equal" }];
        }
    }


    private sealed class Operators : IFilterOperator
    {
        public required string Value { get; set; }
        public required string Text { get; set; }
    }




    private sealed record NotificationDto
    {
        public int Id { get; set; }
        public NotificationType Level { get; set; }
    }


    private enum NotificationType
    {
        ERROR = 1,
        SUCCESS = 2,
        INFORMATION = 3,
        WARNING = 4
    }
}


In program.cs you will need to configure an httpclient

// HttpClient

builder.Services.AddHttpClient("App")




PS Prathap Senthil Syncfusion Team June 19, 2024 02:55 PM UTC

Hi Wuss,


Based on the issue you reported we have resolved it in the following way. Kindly refer to the modified code snippet and sample below for your reference.


 
<div>

    <SfGrid @ref="sfGridRef" TValue="Notification" AllowPaging="true" AllowFiltering="true">

        <SfDataManager Url=@($"api/notifications/odata") Adaptor="Syncfusion.Blazor.Adaptors.WebApiAdaptor"

            HttpClientInstance=@(_hc.CreateClient("App")) />

        <GridFilterSettings Type="Syncfusion.Blazor.Grids.FilterType.Menu" />

        <GridPageSettings PageSize="20" PageCount="5" PageSizes="true" />

        <GridEvents FilterDialogOpening="FilterDialogOpeningHandler" Filtering="FilteringHandler" TValue="Notification" />

        <GridColumns>

            <GridColumn Field=@nameof(Notification.Id) HeaderText="Id" IsIdentity="true" IsPrimaryKey="true"

                Visible="false" />

            <GridColumn Field=@nameof(Notification.Level) HeaderText="Level" AllowEditing="false">

                <FilterTemplate>

                    @{

                        var data = context as PredicateModel<NotificationType>;

                        if (data is not null)

                        {

                            <SfDropDownList Placeholder="Level" DataSource="LevelDropDownSource" TValue="NotificationType"

                                TItem="string" @bind-Value="@data.Value">

                                <DropDownListFieldSettings Text="Level" Value="Level" />

                                <DropDownListEvents TItem="string" ValueChange="Change" TValue="NotificationType"></DropDownListEvents>

                            </SfDropDownList>

                        }

                    }

                </FilterTemplate>

            </GridColumn>

        </GridColumns>

    </SfGrid>

</div>



@code {
public int FilterValue { get; set;  }

 

   public bool IsFlag { get; set; }

 

  public async Task Change(ChangeEventArgs<NotificationType,string > args)

   {

 

       FilterValue = (int)Enum.Parse(typeof(NotificationType),args.Value.ToString());  //here you can get value

       IsFlag = true;

 

   }

 

   public void FilteringHandler(Syncfusion.Blazor.Grids.FilteringEventArgs args)

   {

       if (args.ColumnName == "Level" && IsFlag)

       {

           args.Cancel = true;

           IsFlag = false;

           sfGridRef.FilterByColumnAsync("Level", "equal", FilterValue);

           FilterValue = 0;

       }

   }

 


Reference:
https://blazor.syncfusion.com/documentation/datagrid/filtering#filter-enum-column
https://blazor.syncfusion.com/documentation/datagrid/events#filtered
https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Grids.SfGrid-1.html#Syncfusion_Blazor_Grids_SfGrid_1_FilterByColumnAsync_System_String_System_String_System_Object_System_String_System_Nullable_System_Boolean__System_Nullable_System_Boolean__System_Object_System_Object_System_String_

Regards,
Prathap Senthil


Attachment: blazorbugssyncfusionenummain_4fc4d9b4.zip


WW Wuss Wuzz June 19, 2024 04:24 PM UTC

This does not work I am afraid

args.Cancel does not even exist as a method or property in that event handler.

Is there a place that I can file a bug report to get this fixed?



PS Prathap Senthil Syncfusion Team June 21, 2024 01:55 AM UTC

Based on your concern, we would like to clarify that the Filtering event argument includes a Cancel property. Kindly refer to the API link below for your reference. Are you facing any issues when using the previous solution? If yes, please share the specific issues you encountered. If you have identified and reported an issue as a bug, we will confirm it in this forum and provide the details of the bug.

Reference:
https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Grids.FilteringEventArgs.html#Syncfusion_Blazor_Grids_FilteringEventArgs_Cancel


Loader.
Up arrow icon