Hello,
I'm experiencing quite a few issues with the Syncfusion DataGrid when filtering while using a custom data adaptor. I'm doing the sorting, paging, and filtering on the server-side but my issues revolve around the client-side behavior of the grid itself and its ReadAsync() DataManagerRequest parameter supplied to the custom data adapter.
Two General questions first:
1. Is there a way to prevent ReadAsync()/Server requests on every single key stroke and instead only on enter similar to when using the MenuBar Filter mode FilterBarMode.OnEnter?
2. Is there a way to eliminate the "No Records found" popup below the text input field inside the column menu?
Here is the reproduction steps and description of the behavioral issues. Please note that I have modified the server code to elminate any database operations, and have coded the bare minimum to reproduce the client side behavior following the specific steps below. Attempting some other filter operations besides what is outlined below won't have the server-side code to handle it.
When using Column Menu filtering:
Steps to reproduce odd behavior:
1. Upon component initialization, the grid makes a request with no filter and a Take property of 50 to match the page count of 50. The grid loads 8 records as expected.
2. Clicking the menu icon on the Last Name column, and entering the letter "s" into the last name filter with contains as the default operator, ReadAsync() will fire with DataManagerRequest object containing the "s" value and "contains" operator. However, the Take value is somehow 20 instead of 50. The server then responds with a Count of 4 and the 4 records in question. The column menu filter popup then displays a "No Records Found" notification below the text input field and the grid does not refresh to reflect the four records.
3. At this stage, pressing enter/clicking the Filter button will close the filter menu popup with "s" still in the text input field and will cause another call to ReadAsync(), only this time .Where filters list is null and the Take property is somehow 0. The server returns 8 clients and the grid shows "No records to display".
5. With the grid in this state, and with the column menu filter icon highlighted blue, simply clicking the menu filter icon will cause another called to ReadAsync() with the value still being an empty string despite closing the popup with "s" in the filter textbox. The server returns 8 records again.
6. With no further user input, there is immediately another call to ReadAsync() with the value once again "s" as I would expect, but somehow the Operator is now "Equal" instead of "contains" and the Take value is somehow 0 now. The server blows up trying to do a Fetch next 0 rows and does not return anything to the client.
7. Finally, clicking Clear on the column menu filter will cause a request to be made with a Take of 50, no where filters, and 8 rows are turned and displayed once again in the grid, just as with the initial read of the component. We've come full circle.
In summary, I'm seeing unexpected calls to ReadAsync, unexpected Take values, unexpected Where filters, and unexpected grid display of results.
When using MenuBar Filter Mode (by commenting out line 36 in ClientList.razor):
1.On initial load, ReadAsync() is called with a Take of 50, no filters, and the server returns 8 rows as expected.
2.Typing "s" into the last name filter textbox and pressing enter causes ReadAsync() to run. The Take is 50, but the operator and value are both null on the WhereFilter object.
In this mode, I would like the textbox filters to function like "contains" operators on text fields, "equals" on number and date fields.
Thank you for your help and consideration!
Hi Enoch,
Greeting from Syncfusion Support.
Query -1 :"Is there a way to prevent ReadAsync()/Server requests on every single key stroke and instead only on enter similar to when using the MenuBar Filter mode FilterBarMode.OnEnter?".
Yes, You can prevent this action by rendering the custom component in the Filter Template. But it is not possible to prevent this action by default.
Query-2:" Is there a way to eliminate the "No Records found" popup below the text input field inside the column menu?".
Based on the current architecture of the DataGrid, It is not possible to achieve your requirement. Kindly refer the attached UG documentation link to resolve your issues.
Reference Link: https://blazor.syncfusion.com/documentation/datagrid/custom-binding#handling-filtering-in-custom-adaptor
Hello Balamurugan,
Are there any updates on this issue? The frequent calls to ReadAsync() are not desirable but can be worked with. However, the erroneous filter values is basically making server-side filtering impossible which unfortunately makes this grid component unviable for my needs.
Is there anything I can provide to help your team troubleshoot this issue?
We'd like to clarify that when utilizing the Menu or Excel-like filter in the DataGrid, the behavior is such that when you enter a search term, the grid performs a search across the entire data list and displays relevant values in the filter box. Since you have used the CustomAdaptor triggers the ReadAsync method each time you enter a value in the filter textbox. This is a default behavior of the grid.
Hi Prathap,
I went ahead and implemented a custom column filter component per your team's recommendation. The component is showing up fine, and is calling
await GridRef.FilterByColumnAsync(ColumnFieldName, filterOperator, filterValue);
With the correct values that I would expect, which in turn invokes the custom data adaptor's ReadAsync() method as I would expect. However, the values in the DataManagerRequest's Where collection are null for the operator and filter value.
Inside my custom filter component, I'm also trying to obtain an PredicateModel<string> from the context but the cast is failing resulting in a null value.
I've attached a bare bones sample app reproducing the issue with the following code. For some reason the ReadAsync() is not initially called to populate the grid with data but you can reproduce the issue by dropping down the LastName column filter, typing in a value, and pressing the filter button. The rows will show up in the grid after that.
Here is my custom column filter component:
@using Syncfusion.Blazor.Inputs;
<div>
<SfDropDownList TValue="string" TItem="FilterOption" DataSource="@FilterOptions" @bind-Value="@filterOperator" Placeholder="Select an operator" Width="100%">
<DropDownListFieldSettings Text="DisplayText" Value="Value"></DropDownListFieldSettings>
</SfDropDownList>
<div style="margin-top: 10px;">
<SfTextBox Placeholder="Enter value" Width="100%" @bind-Value="@filterValue" Input="InputChanged" />
</div>
<div style="margin-top: 10px;">
<SfButton OnClick="FilterButtonClicked">Filter</SfButton>
<SfButton OnClick="ClearButtonClicked">Clear</SfButton>
</div>
</div>
<style>
.e-filter-popup .e-footer-content {
display: none;
}
.e-flmenu-maindiv .e-flm_optrdiv {
display: none
}
</style>
@typeparam GridTValue
@code {
[Parameter]
public string ColumnFieldName { get; set; }
[Parameter]
public SfGrid<GridTValue> GridRef { get; set; }
[CascadingParameter]
public object context { get; set; }
public List<FilterOption> FilterOptions { get; set; } = new List<FilterOption>
{
new FilterOption { DisplayText = "Contains", Value = "contains" },
new FilterOption { DisplayText = "Equals", Value = "equal" },
new FilterOption { DisplayText = "Starts With", Value = "startswith" },
new FilterOption { DisplayText = "Ends With", Value = "endswith" },
new FilterOption { DisplayText = "Not Equals", Value = "notequal" }
};
private string filterValue = "";
private string filterOperator = "contains";
private async Task InputChanged(InputEventArgs args)
{
filterValue = args.Value;
}
private async Task ApplyFilterToGrid()
{
//var c = (context as PredicateModel<string>);
//c is null here
await GridRef.FilterByColumnAsync(ColumnFieldName, filterOperator, filterValue);
}
private async Task ClearFilterFromGrid()
{
await GridRef.ClearFilteringAsync(ColumnFieldName);
}
private async Task FilterButtonClicked(MouseEventArgs args)
{
await ApplyFilterToGrid();
}
private async Task ClearButtonClicked(MouseEventArgs args)
{
await ClearFilterFromGrid();
}
public class FilterOption
{
public string DisplayText { get; set; }
public string Value { get; set; }
}
}
And my Grid:
@page "/"
@using CustomGridFilterNotWorking.Client.Shared
@using CustomGridFilterNotWorking.Shared;
@using PantryManager.Client.Adaptors;
<SfGrid ID="ClientListGrid" @ref="ClientListDataGridRef" TValue="ClientListDTO" AllowPaging="true" AllowSorting="true" AllowFiltering="true">
<GridTemplates>
</GridTemplates>
<GridFilterSettings Type="Syncfusion.Blazor.Grids.FilterType.Menu"></GridFilterSettings>
<GridPageSettings PageSize="50" PageSizes="@PagerDropdown" PageCount="3"></GridPageSettings>
<SfDataManager @ref="ClientListDataManagerRef" Adaptor="Adaptors.CustomAdaptor" AdaptorInstance="@typeof(ClientListAdaptor)"></SfDataManager>
<GridSortSettings>
<GridSortColumns>
<GridSortColumn Field="LastName" Direction="SortDirection.Ascending"></GridSortColumn>
</GridSortColumns>
</GridSortSettings>
<GridColumns>
<GridColumn Field=@nameof(ClientListDTO.LastName) HeaderText="Last Name" Width="100">
<FilterTemplate>
<StringColumnFilter GridRef="@ClientListDataGridRef" ColumnFieldName="LastName" GridTValue="ClientListDTO"></StringColumnFilter>
</FilterTemplate>
</GridColumn>
<GridColumn Field=@nameof(ClientListDTO.FirstName) HeaderText="First Name" Width="100"></GridColumn>
</GridColumns>
</SfGrid>
@code{
private SfDataManager ClientListDataManagerRef { get; set; }
private SfGrid<ClientListDTO> ClientListDataGridRef { get; set; }
public string[] PagerDropdown { get; set; } = new string[] { "All", "50", "100", "250", "500" };
protected override async Task OnInitializedAsync()
{
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await ClientListDataGridRef.Refresh();
}
}
}
And my custom data adaptor:
using Syncfusion.Blazor.Data;
using Syncfusion.Blazor;
using Syncfusion.Blazor.Grids;
using CustomGridFilterNotWorking.Shared;
namespace PantryManager.Client.Adaptors
{
public class ClientListAdaptor : DataAdaptor
{
public ClientListAdaptor()
{
}
public async override Task<object> ReadAsync(DataManagerRequest dataManagerRequest, string key = null)
{
List<Sort> sorts = dataManagerRequest.Sorted.ToList();
List<WhereFilter> whereFilters = dataManagerRequest.Where.ToList();
//whereFilters contains one item but the filter operator and filter value are null
List<ClientListDTO> clientListDTOs = new List<ClientListDTO>();
clientListDTOs.Add(new ClientListDTO() { FirstName = "Bruce", LastName = "Wayne" });
clientListDTOs.Add(new ClientListDTO() { FirstName = "Charles", LastName = "Xavier" });
clientListDTOs.Add(new ClientListDTO() { FirstName = "Chris", LastName = "Farley" });
await Task.Delay(1000);
DataResult dataResult = new DataResult()
{
Result = clientListDTOs,
Count = clientListDTOs.Count
};
return dataResult;
}
}
}
Based on the reported problem, we suggest using the filtering operation to be handled in the custom adapter to avoid the problem and achieve your requirement. Kindly refer to the code snippet and sample below for your reference.
|
public async override Task<object> ReadAsync(DataManagerRequest dataManagerRequest, string key = null) {
List<ClientListDTO> clientListDTOs = new List<ClientListDTO>(); clientListDTOs.Add(new ClientListDTO() { FirstName = "Bruce", LastName = "Wayne" }); clientListDTOs.Add(new ClientListDTO() { FirstName = "Charles", LastName = "Xavier" }); clientListDTOs.Add(new ClientListDTO() { FirstName = "Chris", LastName = "Farley" });
IEnumerable<ClientListDTO> DataSource = clientListDTOs;
if (dataManagerRequest.Where != null && dataManagerRequest.Where.Count > 0) { //List<WhereFilter> whereFilters = dataManagerRequest.Where.ToList();
// Filtering DataSource = DataOperations.PerformFiltering(DataSource, dataManagerRequest.Where, dataManagerRequest.Where[0].Operator); }
int count = DataSource.Cast<ClientListDTO>().Count();
//await Task.Delay(1000);
// return dataManagerRequest.RequiresCounts ? new DataResult() { Result = DataSource, Count = count } : (object)DataSource; DataResult dataResult = new DataResult() { Result = DataSource, Count = count };
return dataResult; }
|
Hi Prathap. I think we had a some miscommunication. The problem I'm having is that I'm unable to obtain the current filters for the grid in order to make a network call to an API that will then perform the server-side paging/filtering/sorting. My current code essentially converts SyncFusion's Sort and WhereFilter objects from their respective collections off the DataManagerRequest, to some custom types mimicking those, and then passes those custom types to the server to perform the operations server-side within the database. The problem is that the WhereFilter collection doesn't have the actual values that I inputted through the custom column filter when making the call to
await GridRef.FilterByColumnAsync(ColumnFieldName, filterOperator, filterValue);
Here's the current code:
public async override Task<object> ReadAsync(DataManagerRequest dataManagerRequest, string key = null)
{
DataGridRequest customRequest = new DataGridRequest();
customRequest.Skip = dataManagerRequest.Skip;
customRequest.Take = dataManagerRequest.Take;
if (dataManagerRequest.Sorted.IsNotEmpty())
{
//syncfusion has the sorts in reverse for some reason in its internal collection, reverse it first
IEnumerable<Sort> reversedSorts = dataManagerRequest.Sorted.AsEnumerable().Reverse();
customRequest.SortDescriptors = reversedSorts.Select(s => new DataGridSortDescriptor() { Name = s.Name, Direction = s.Direction == "ascending" ? SortDirection.ASC : SortDirection.DESC }).ToList();
}
var filterVal = dataManagerRequest.Where[0].value; // is null
var filterOperator = dataManagerRequest.Where[0].Operator; //is null
if (dataManagerRequest.Where != null && dataManagerRequest.Where.Any())
{
customRequest.FilterDescriptors = dataManagerRequest.Where.Select(w => ConvertToFilterDescriptor(w)).ToList();
}
//make an API call to get the data
ClientListDataResult result = await clientService.GetClientList(customRequest);
DataResult dataResult = new DataResult()
{
Result = result.ClientList,
Count = result.Count
};
return dataResult;
}
The following values are null:
var filterVal = dataManagerRequest.Where[0].value; // is null
var filterOperator = dataManagerRequest.Where[0].Operator; //is null
Without them, I'm unable to do the server-side filtering. The sample I attached reproduces this behavior.
By the way, How do I insert a code block within a forum post to improve readability? Thank you for your help with this!
Based on your requirements, if you need to take the filter value and filter operator, you can use the Predicate list property in the Where list for the DataManagerRequest class. Please refer to the code snippet and screenshot below for your reference.
|
public async override Task<object> ReadAsync(DataManagerRequest dataManagerRequest, string key = null) {
List<ClientListDTO> clientListDTOs = new List<ClientListDTO>(); clientListDTOs.Add(new ClientListDTO() { FirstName = "Bruce", LastName = "Wayne" }); clientListDTOs.Add(new ClientListDTO() { FirstName = "Charles", LastName = "Xavier" }); clientListDTOs.Add(new ClientListDTO() { FirstName = "Chris", LastName = "Farley" });
IEnumerable<ClientListDTO> DataSource = clientListDTOs;
//var filterVal = dataManagerRequest.Where[0].value; // is null
//var filterOperator = dataManagerRequest.Where[0].Operator; //is null if (dataManagerRequest.Where != null && dataManagerRequest.Where.Count > 0) { //List<WhereFilter> whereFilters = dataManagerRequest.Where.ToList(); var filterVal = dataManagerRequest.Where[0].predicates[0].value; Console.WriteLine("FilterValue:"+filterVal);
var filterOperator = dataManagerRequest.Where[0].predicates[0].Operator; Console.WriteLine("FilterOperator:" + filterOperator); // Filtering DataSource = DataOperations.PerformFiltering(DataSource, dataManagerRequest.Where, dataManagerRequest.Where[0].Operator); }
int count = DataSource.Cast<ClientListDTO>().Count();
//await Task.Delay(1000);
// return dataManagerRequest.RequiresCounts ? new DataResult() { Result = DataSource, Count = count } : (object)DataSource; DataResult dataResult = new DataResult() { Result = DataSource, Count = count };
return dataResult; } } |
|
|
Regarding your additional question about inserting a code block within a forum post, please refer to the screenshot below. Use the 'code' option in the reply box.
|
|
Hi Prathap,
That works great! I'm able to send the correct filter operators and values to the server now and the filtering is working on multiple columns as I would expect. I also managed to initialize the custom filter component with the current column filters so that it's initialized properly each time it is shown.
However, there are two issues I'm not able to resolve:
-Setting focus to the textbox input when the component is shown
-Handling the "enter" key press to apply the filter to the grid
For the first problem, I've added a onkeyup event handler to the textbox and dropdown list that does the following:
private async Task HandleKeyUp(KeyboardEventArgs args)
{
if (args.Code == "Enter" || args.Key == "Enter")
{
//never being hit, something else is capturing the enter key press before this code gets hit
await ApplyFilterToGrid();
}
}
However, that code is never hit. The even fires as I would expect for other keyboard inputs besides enter.
As for the second issue, I'm attempting the following:
protected override async void OnAfterRender(bool firstRender)
{
if(firstRender)
{
//Not setting focus to the textbox, the dropdown instead gets focus
await JSRuntime.InvokeVoidAsync("FocusColMenuFilterTextbox");
}
} [custom-app.js]
function CloseColumnFilterDialog() {
document.getElementById("ClientListGrid").click();
}
function FocusColMenuFilterTextbox() {
document.getElementById("colMenuFilterTextbox").focus();
}
The javascript method is called, however, the textbox doesn't receive focus, but instead the dropdown does.
It's unclear if there are other components within syncfusion that are handling/overriding these custom behaviors.
I believe these are the last two issues related to the custom column filter component. Phew! Here is the full column filter component for reference:
@using Syncfusion.Blazor.Inputs;
@inject IJSRuntime JSRuntime
<div>
<SfDropDownList TValue="string" TItem="FilterOption" DataSource="@FilterOptions" @bind-Value="@filterOperator" @onkeyup="HandleKeyUp" Placeholder="Select an operator" Width="100%">
<DropDownListFieldSettings Text="DisplayText" Value="Value"></DropDownListFieldSettings>
</SfDropDownList>
<div style="margin-top: 10px;">
<SfTextBox ID="colMenuFilterTextbox" Placeholder="Enter value" Width="100%" @bind-Value="@filterValue" @onkeyup="HandleKeyUp" Input="InputChanged" on />
</div>
<div style="margin-top: 10px;">
<SfButton type="button" IsPrimary="true" OnClick="FilterButtonClicked">Filter</SfButton>
<SfButton type="button" CssClass="btn btn-secondary" OnClick="ClearButtonClicked">Clear</SfButton>
</div>
</div>
<style>
.e-filter-popup .e-footer-content {
display: none;
}
.e-flmenu-maindiv .e-flm_optrdiv {
display: none
}
</style>
@typeparam GridTValue
@code {
[Parameter]
public string ColumnFieldName { get; set; }
[Parameter]
public SfGrid<GridTValue> GridRef { get; set; }
[CascadingParameter]
public object context { get; set; }
private string filterValue = "";
private string filterOperator = "contains";
public List<FilterOption> FilterOptions { get; set; } = new List<FilterOption>
{
new FilterOption { DisplayText = "Contains", Value = "contains" },
new FilterOption { DisplayText = "Equals", Value = "equal" },
new FilterOption { DisplayText = "Starts With", Value = "startswith" },
new FilterOption { DisplayText = "Ends With", Value = "endswith" },
new FilterOption { DisplayText = "Not Equals", Value = "notequal" }
};
protected override void OnInitialized()
{
//need to initialize the filter textbox and operator dropdown to the current filter values for this column
var columnFilter = GridRef.FilterSettings.Columns?.FirstOrDefault(f => f.Field == ColumnFieldName);
if (columnFilter != null)
{
filterOperator = GetFilterOperatorStringFromEnum(columnFilter.Operator);
filterValue = columnFilter.Value?.ToString();
}
}
private async Task HandleKeyUp(KeyboardEventArgs args)
{
if (args.Code == "Enter" || args.Key == "Enter")
{
//never being hit, something else is capturing the enter key press before this code gets hit
await ApplyFilterToGrid();
}
}
protected override async void OnAfterRender(bool firstRender)
{
if(firstRender)
{
//Not setting focus to the textbox, the dropdown instead gets focus
await JSRuntime.InvokeVoidAsync("FocusColMenuFilterTextbox");
}
}
private async Task HandleValidSubmit()
{
await ApplyFilterToGrid();
}
private async Task InputChanged(InputEventArgs args)
{
filterValue = args.Value;
}
private async Task ApplyFilterToGrid()
{
await JSRuntime.InvokeVoidAsync("CloseColumnFilterDialog");
await GridRef.FilterByColumnAsync(ColumnFieldName, filterOperator, filterValue);
}
private async Task ClearFilterFromGrid()
{
await JSRuntime.InvokeVoidAsync("CloseColumnFilterDialog");
await GridRef.ClearFilteringAsync(ColumnFieldName);
}
private async Task FilterButtonClicked(MouseEventArgs args)
{
await ApplyFilterToGrid();
}
private async Task ClearButtonClicked(MouseEventArgs args)
{
await ClearFilterFromGrid();
}
public class FilterOption
{
public string DisplayText { get; set; }
public string Value { get; set; }
}
private string GetFilterOperatorStringFromEnum(Syncfusion.Blazor.Operator op)
{
switch (op)
{
case Operator.Contains:
return "contains";
case Operator.Equal:
return "equal";
case Operator.StartsWith:
return "startswith";
case Operator.EndsWith:
return "endswith";
case Operator.NotEqual:
return "notequal";
default:
throw new Exception("Filter operator not supported in string column");
}
}
}
I've attached an updated sample for you reproducing the two issues.
Thank you for your assistance with this, much appreciated!
Regarding your requirement, we recommend focusing on the textbox element and setting the TabIndex to '-1' for the dropdown element. Please refer to the code snippet below for your reference.
|
<div> <SfDropDownList TValue="string" TItem="FilterOption" DataSource="@FilterOptions" TabIndex="-1" @bind-Value="@filterOperator" @onkeyup="HandleKeyUp" Placeholder="Select an operator" Width="100%"> <DropDownListFieldSettings Text="DisplayText" Value="Value"></DropDownListFieldSettings> </SfDropDownList> <div style="margin-top: 10px;"> <SfTextBox ID="colMenuFilterTextbox" Placeholder="Enter value" Width="100%" @bind-Value="@filterValue" @onkeyup="HandleKeyUp" Input="InputChanged" on /> </div> <div style="margin-top: 10px;"> <SfButton type="button" IsPrimary="true" OnClick="FilterButtonClicked">Filter</SfButton> <SfButton type="button" CssClass="btn btn-secondary" OnClick="ClearButtonClicked">Clear</SfButton> </div> </div>
|
When you click the 'Enter' button, the 'OnActionBegin' event will
trigger, and the 'RequestType Filtering' will be activated. At this point, you
can cancel the normal behavior and implement a custom scenario, as shown in the
code snippet below.
|
<SfGrid ID="ClientListGrid" @ref="ClientListDataGridRef" TValue="ClientListDTO" AllowPaging="true" AllowSorting="true" AllowFiltering="true"> <GridTemplates> </GridTemplates> <GridEvents OnActionBegin="ActionBeginHandler" TValue="ClientListDTO"></GridEvents> </SfGrid>
@code{ private SfDataManager ClientListDataManagerRef { get; set; } private SfGrid<ClientListDTO> ClientListDataGridRef { get; set; } public string[] PagerDropdown { get; set; } = new string[] { "All", "50", "100", "250", "500" };
public StringColumnFilter<ClientListDTO> stringColumnFilter{ get; set; } protected override async Task OnInitializedAsync() {
}
protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { await ClientListDataGridRef.Refresh(); } }
public async Task ActionBeginHandler(ActionEventArgs<ClientListDTO> args) { if (args.RequestType.Equals(Syncfusion.Blazor.Grids.Action.Filtering)) {
args.Cancel = true;// Prevent the default behavior await stringColumnFilter.ApplyFilterToGrid();
} }
} |
Hi Prathap,
Thank you for your recommendations. I managed to get the enter key press issue working using a different approach. Your solution, if I understood it correctly, resulted in an infinite loop.
The initial entry point is in ActionBeginHandler after pressing enter, which is cancelled, which then calls my ApplyFilterToGrid(), which applies the filter to the grid which in turn calls ActionBeginHandler again and the cycle repeats.
Moreover, requiring to keep references to the custom filter components is pretty unwieldy considering that all my columns will require a custom component, and some columns may eventually not be known at compile-time but added dynamically to the grid.
The approach I took (provided by ChatGPT :) ) is as follows:
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await JSRuntime.InvokeVoidAsync("customFunctions.addEventListenerToInput",
"colMenuFilterTextbox",
DotNetObjectReference.Create(this));
}
}
[JSInvokable]
public async Task HandleEnterKeyDown()
{
await ApplyFilterToGrid();
}
And in my JS file:
window.customFunctions = {
addEventListenerToInput: function (elementId, dotNetObject) {
const inputElement = document.getElementById(elementId);
if (!inputElement) {
console.error("Element not found:", elementId);
return;
}
inputElement.addEventListener("keydown", function (event) {
if (event.key === "Enter" || event.keyCode === 13) {
event.preventDefault();
dotNetObject.invokeMethodAsync("HandleEnterKeyDown");
}
});
}
};
A keydown event listener is added to the textbox, which invokes a method within the blazor component to apply the filter to the grid. This appears to preempt any event handling by syncfusion components.
There is one other problem with the column filter menu and that is when I click off of the filter menu somewhere else causing it to close. If the filter menu already contains a value in the textbox, and I click off of it, the ReadAsync() method fires. It will fire even if I don't change the value in the textbox (assuming it had one previously set which was loaded once the component was reshown). When I do this, the Where list on the DataManagerRequest object is null. It's null even if I have more than one column with this custom filter component and they all have active filter values. I would think the ReadAsync() should never fire if the user clicks off of the menu, and that doing so effectively acts as a "cancel", regardless of what filter values the component was initialized with or what changes were made inside of it.
If the filter menu does not have a filter value already, and I type one in and click off of the menu, the ReadAsync does not fire. This is what I would expect.
I'm not sure what's causing this behavior nor how to approach solving it. This has turned out to be a lot harder than I imagined :(
I've attached a sample reproducing the issue. Thank you!
We have considered it as a bug and logged an issue “Unnecessary call to ReadAsync method when filtering records using filtertemplate and clicking outside of Menufilterdialog”for the same. Thank you for taking the time to report this issue and helping us to improve our product. At Syncfusion, we are committed to fix all validated defects (subject to technological feasibility and Product Development Life Cycle) and this fix will be included in our upcoming patch release.
You can now track the current status of your request, review the proposed resolution timeline, and contact us for any further inquiries through this link.
Disclaimer: “Inclusion of this solution in the weekly release may change due to other factors including but not limited to QA checks and works reprioritization”
Until then we appreciate your patience.
Hi Encoh,
We are glad to announce that, we have included the fix for the issue “Unnecessary
call to ReadAsync method when filtering records using filtertemplate and
clicking outside of Menufilterdialog” in our 23.1.42 release. So
please upgrade to our latest version of the Syncfusion package to resolve the
reported issue.
NuGet: https://www.nuget.org/packages/Syncfusion.Blazor.Grid
We thank you for your support and appreciate your patience in waiting for this
release. Please get in touch with us if you would require any further
assistance.
Regards,
Prathap S
Hi Prathap,
I updated my components and the fix works great. Thank you for your help and the quick turnaround time!
Thanks for the update,
We are glad to hear that the issue has been successfully resolved. We will now close this thread.
I'm not sure what's causing this behavior nor how to approach solving it. This has turned out to be a lot harder than I imagined :(