New to Telerik UI for Blazor? Start a free 30-day trial
Persist Grid Filter Operator After Value Clear
Updated on Jul 31, 2025
Environment
Product |
Grid for Blazor, TreeList for Blazor |
Description
This KB article answers the following questions:
- How to keep the same filter operator across multiple filter operations in a Grid column?
- The set filter operator is lost when I clear the filter value. How to persist it?
- How to maintain a non-default filter operator when the user removes the current filter value?
Solution
The suggested approach below applies to both the Grid and the TreeList.
- Subscribe to the Grid
OnStateChanged
event. - Check the
PropertyName
value in theOnStateChanged
event argument to detect when the user is filtering. - Save the currently applied filter operators for each filtered column to some custom collection.
- Compare the previously saved filters to the current ones. When the user removes the filter of a column, save the previous filter operator.
- Once the user filters by a column that has a saved filter operator, restore this operator.
Persist Grid filter operator
@using Telerik.DataSource
<TelerikGrid Data="@GridData"
TItem="@Product"
FilterMode="GridFilterMode.FilterRow"
Pageable="true"
Sortable="true"
OnStateChanged="@OnGridStateChanged">
<GridColumns>
<GridColumn Field="@nameof(Product.Name)" />
<GridColumn Field="@nameof(Product.Group)" />
<GridColumn Field="@nameof(Product.Price)" DisplayFormat="{0:c2}" />
<GridColumn Field="@nameof(Product.Quantity)" DisplayFormat="{0:n0}" />
<GridColumn Field="@nameof(Product.Released)" DisplayFormat="{0:d}" />
<GridColumn Field="@nameof(Product.Discontinued)" />
</GridColumns>
</TelerikGrid>
@code {
private List<Product> GridData { get; set; } = new();
private List<FilterDescriptor> SavedFilterDescriptors { get; set; } = new();
private Dictionary<string, FilterOperator> ClearedFilterOperators { get; set; } = new();
private void OnGridStateChanged(GridStateEventArgs<Product> args)
{
// Check if the user has changed the filter configuration
if (args.PropertyName == "FilterDescriptors")
{
IEnumerable<CompositeFilterDescriptor> currentFilters = args.GridState.FilterDescriptors.OfType<CompositeFilterDescriptor>();
// Iterate previously saved filters and compare to current ones
foreach (FilterDescriptor savedOneColumnFd in SavedFilterDescriptors)
{
string savedMember = savedOneColumnFd.Member;
object savedFilterValue = savedOneColumnFd.Value;
FilterOperator savedOperator = savedOneColumnFd.Operator;
if (!string.IsNullOrEmpty(savedFilterValue?.ToString()))
{
// Search for current filters for the saved column
FilterDescriptor? currentOneColumnFd = currentFilters
.FirstOrDefault(x => x.FilterDescriptors.OfType<FilterDescriptor>().Any(y => y.Member == savedMember))?
.FilterDescriptors.OfType<FilterDescriptor>().First();
// Check if filter for the current column no longer exists
if (currentOneColumnFd is null)
{
// Save filter operator for future restore
if (ClearedFilterOperators.ContainsKey(savedMember))
{
ClearedFilterOperators[savedMember] = savedOperator;
}
else
{
ClearedFilterOperators.Add(savedMember, savedOperator);
}
}
}
}
SavedFilterDescriptors.Clear();
// Iterate current filters
foreach (CompositeFilterDescriptor currentOneColumnCfd in currentFilters)
{
IEnumerable<FilterDescriptor> currentOneColumnFds = currentOneColumnCfd.FilterDescriptors.OfType<FilterDescriptor>();
string currentMember = currentOneColumnFds.First().Member;
FilterOperator currentOperator = currentOneColumnFds.First().Operator;
object currentValuе = currentOneColumnFds.First().Value;
// Detect new filter value after clearing and restore previous operator
if (ClearedFilterOperators.ContainsKey(currentMember))
{
currentOneColumnFds.First().Operator = currentOperator = ClearedFilterOperators[currentMember];
ClearedFilterOperators.Remove(currentMember);
}
// Save current filter state
SavedFilterDescriptors.Add(new FilterDescriptor() { Member = currentMember, Operator = currentOperator, Value = currentValuе });
}
}
}
protected override void OnInitialized()
{
var rnd = Random.Shared;
for (int i = 1; i <= 57; i++)
{
GridData.Add(new Product()
{
Id = i,
Name = $"Name {i} {(char)rnd.Next(65, 91)}{(char)rnd.Next(65, 91)}",
Group = $"Group {i % 3 + 1}",
Price = rnd.Next(1, 100) * 1.23m,
Quantity = rnd.Next(0, 10000),
Released = DateTime.Today.AddDays(-rnd.Next(60, 1000)),
Discontinued = i % 4 == 0
});
}
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Group { get; set; } = string.Empty;
public decimal Price { get; set; }
public int Quantity { get; set; }
public DateTime Released { get; set; }
public bool Discontinued { get; set; }
}
}