New to Telerik UI for Blazor? Start a free 30-day trial
How to Use Custom Grid DateTime Filters
Updated on Jul 2, 2026
Environment
| Product | Grid for Blazor |
Description
This KB shows how to apply custom DateTime filters in the Grid about periods that do not use fixed dates, for example, the "last 10 days" or "next 2 months".
Solution
- Implement a filter template for the custom filtering UI.
- Convert the custom filtering logic to match the built-in Telerik
FilterDescriptorcapabilities with regard to theOperatorandValue.
Using a custom DateTime filter in the Grid for last/next days/months
@using Telerik.DataSource
<TelerikGrid Data="@GridData"
TItem="@Order"
FilterMode="GridFilterMode.FilterRow"
Height="90vh"
Pageable="true"
PageSize="20"
Sortable="true">
<GridColumns>
<GridColumn Field="@nameof(Order.Customer)" />
<GridColumn Field="@nameof(Order.Product)" />
<GridColumn Field="@nameof(Order.Price)" DisplayFormat="{0:c2}" />
<GridColumn Field="@nameof(Order.Quantity)" DisplayFormat="{0:n0}" />
<GridColumn Field="@nameof(Order.DeliveryDate)" DisplayFormat="{0:D}" Title="Delivery Date" Width="320px">
<FilterCellTemplate>
<TelerikDropDownList Data="@(Enum.GetValues<LastNextEnum>())"
Value="@LastNextOperator"
ValueChanged="@(async (LastNextEnum newValue) => await LastNextOperatorChanged(newValue, context))"
Width="6em">
<DropDownListSettings>
<DropDownListPopupSettings Height="auto" />
</DropDownListSettings>
</TelerikDropDownList>
<TelerikNumericTextBox Value="@LastNextValue"
ValueChanged="@(async (int? newValue) => await LastNextValueChanged(newValue, context))"
DebounceDelay="500"
Min="1"
Width="5em" />
<TelerikDropDownList Data="@(Enum.GetValues<DaysMonthsEnum>())"
Value="@DaysMonthsOperator"
ValueChanged="@(async (DaysMonthsEnum newValue) => await DaysMonthsOperatorChanged(newValue, context))"
Width="7em">
<DropDownListSettings>
<DropDownListPopupSettings Height="auto" />
</DropDownListSettings>
</TelerikDropDownList>
<TelerikButton Icon="@SvgIcon.FilterClear"
Enabled="@LastNextValue.HasValue"
OnClick="@(async() => await OnLastNextClear(context))" />
</FilterCellTemplate>
</GridColumn>
</GridColumns>
</TelerikGrid>
@code {
private List<Order> GridData { get; set; } = new();
private LastNextEnum LastNextOperator { get; set; } = LastNextEnum.Last;
private int? LastNextValue { get; set; }
private DaysMonthsEnum DaysMonthsOperator { get; set; } = DaysMonthsEnum.Days;
private async Task LastNextOperatorChanged(LastNextEnum newValue, FilterCellTemplateContext context)
{
LastNextOperator = newValue;
await OnCustomDateFilterChanged(context);
}
private async Task LastNextValueChanged(int? newValue, FilterCellTemplateContext context)
{
LastNextValue = newValue;
await OnCustomDateFilterChanged(context);
}
private async Task DaysMonthsOperatorChanged(DaysMonthsEnum newValue, FilterCellTemplateContext context)
{
DaysMonthsOperator = newValue;
await OnCustomDateFilterChanged(context);
}
private async Task OnLastNextClear(FilterCellTemplateContext context)
{
LastNextValue = default;
await context.ClearFilterAsync();
}
private async Task OnCustomDateFilterChanged(FilterCellTemplateContext context)
{
if (LastNextValue.HasValue)
{
context.FilterDescriptor.LogicalOperator = FilterCompositionLogicalOperator.And;
context.FilterDescriptor.FilterDescriptors.Clear();
context.FilterDescriptor.FilterDescriptors.Add(new FilterDescriptor()
{
Member = nameof(Order.DeliveryDate),
Operator = FilterOperator.IsGreaterThanOrEqualTo,
Value = LastNextOperator == LastNextEnum.Last
? (DaysMonthsOperator == DaysMonthsEnum.Days ? DateTime.Today.AddDays(-LastNextValue.Value) : DateTime.Today.AddMonths(-LastNextValue.Value))
: DateTime.Today
});
context.FilterDescriptor.FilterDescriptors.Add(new FilterDescriptor()
{
Member = nameof(Order.DeliveryDate),
Operator = FilterOperator.IsLessThanOrEqualTo,
Value = LastNextOperator == LastNextEnum.Last
? DateTime.Today
: (DaysMonthsOperator == DaysMonthsEnum.Days ? DateTime.Today.AddDays(LastNextValue.Value) : DateTime.Today.AddMonths(LastNextValue.Value))
});
await context.FilterAsync();
}
else
{
await context.ClearFilterAsync();
}
}
protected override void OnInitialized()
{
Random rnd = Random.Shared;
int halfCount = 100;
for (int i = 1; i <= halfCount * 2; i++)
{
GridData.Add(new Order()
{
Id = i,
Customer = $"Customer {i} {(char)rnd.Next(65, 91)}{(char)rnd.Next(65, 91)}",
Product = $"Product {i % 7 + 1}",
Price = rnd.Next(1, 100) * 1.23m,
Quantity = rnd.Next(0, 100),
DeliveryDate = DateTime.Today.AddDays(-halfCount + i - 1)
});
}
}
public class Order
{
public int Id { get; set; }
public string Customer { get; set; } = string.Empty;
public string Product { get; set; } = string.Empty;
public decimal Price { get; set; }
public int Quantity { get; set; }
public DateTime DeliveryDate { get; set; }
}
private enum LastNextEnum
{
Last,
Next
}
private enum DaysMonthsEnum
{
Days,
Months
}
}
Notes
You can implement a similar UX outside the Grid filter templates, for example, in the Grid ToolBar. In that case, use the Grid state methods to retrieve the current filter descriptors and then update or remove them.