Skip to content

Commit c19f8b7

Browse files
authored
kb(Grid): Add KB for last/next period filter (#3770)
1 parent 958796a commit c19f8b7

2 files changed

Lines changed: 193 additions & 0 deletions

File tree

components/grid/templates/filter.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,4 +408,5 @@ The template receives a `context` of type `FilterMenuTemplateContext` that provi
408408
* [Live Demo: Grid Custom Filter Row](https://demos.telerik.com/blazor-ui/grid/custom-filter-row)
409409
* [Live Demo: Grid Custom Filter Menu](https://demos.telerik.com/blazor-ui/grid/custom-filter-menu)
410410
* [KB: Use Filter Operator DropDown List in Filter Row Template](slug:grid-kb-filter-operator-dropdown)
411+
* [KB: Use Custom DateTime Filters in a Filter Template](slug:grid-kb-custom-datetime-filters)
411412
* [Blazor Grid](slug:grid-overview)
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
---
2+
title: How to Use Custom Grid DateTime Filters
3+
description: Learn how to apply a custom date filter in the Grid about the last/next days/months.
4+
type: how-to
5+
slug: grid-kb-custom-datetime-filters
6+
tags: telerik, blazor, grid, filter
7+
ticketid: 1630757
8+
res_type: kb
9+
components: ["grid"]
10+
---
11+
12+
## Environment
13+
14+
<table>
15+
<tbody>
16+
<tr>
17+
<td>Product</td>
18+
<td>Grid for Blazor</td>
19+
</tr>
20+
</tbody>
21+
</table>
22+
23+
## Description
24+
25+
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".
26+
27+
## Solution
28+
29+
1. Implement a [filter template](slug:grid-templates-filter) for the custom filtering UI.
30+
1. Convert the custom filtering logic to match the built-in Telerik [`FilterDescriptor`](slug:Telerik.DataSource.FilterDescriptor) capabilities with regard to the `Operator` and `Value`.
31+
32+
>caption Using a custom DateTime filter in the Grid for last/next days/months
33+
34+
````RAZOR
35+
@using Telerik.DataSource
36+
37+
<TelerikGrid Data="@GridData"
38+
TItem="@Order"
39+
FilterMode="GridFilterMode.FilterRow"
40+
Height="90vh"
41+
Pageable="true"
42+
PageSize="20"
43+
Sortable="true">
44+
<GridColumns>
45+
<GridColumn Field="@nameof(Order.Customer)" />
46+
<GridColumn Field="@nameof(Order.Product)" />
47+
<GridColumn Field="@nameof(Order.Price)" DisplayFormat="{0:c2}" />
48+
<GridColumn Field="@nameof(Order.Quantity)" DisplayFormat="{0:n0}" />
49+
<GridColumn Field="@nameof(Order.DeliveryDate)" DisplayFormat="{0:D}" Title="Delivery Date" Width="320px">
50+
<FilterCellTemplate>
51+
<TelerikDropDownList Data="@(Enum.GetValues<LastNextEnum>())"
52+
Value="@LastNextOperator"
53+
ValueChanged="@(async (LastNextEnum newValue) => await LastNextOperatorChanged(newValue, context))"
54+
Width="6em">
55+
<DropDownListSettings>
56+
<DropDownListPopupSettings Height="auto" />
57+
</DropDownListSettings>
58+
</TelerikDropDownList>
59+
<TelerikNumericTextBox Value="@LastNextValue"
60+
ValueChanged="@(async (int? newValue) => await LastNextValueChanged(newValue, context))"
61+
DebounceDelay="500"
62+
Min="1"
63+
Width="5em" />
64+
<TelerikDropDownList Data="@(Enum.GetValues<DaysMonthsEnum>())"
65+
Value="@DaysMonthsOperator"
66+
ValueChanged="@(async (DaysMonthsEnum newValue) => await DaysMonthsOperatorChanged(newValue, context))"
67+
Width="7em">
68+
<DropDownListSettings>
69+
<DropDownListPopupSettings Height="auto" />
70+
</DropDownListSettings>
71+
</TelerikDropDownList>
72+
<TelerikButton Icon="@SvgIcon.FilterClear"
73+
Enabled="@LastNextValue.HasValue"
74+
OnClick="@(async() => await OnLastNextClear(context))" />
75+
</FilterCellTemplate>
76+
</GridColumn>
77+
</GridColumns>
78+
</TelerikGrid>
79+
80+
@code {
81+
private List<Order> GridData { get; set; } = new();
82+
83+
private LastNextEnum LastNextOperator { get; set; } = LastNextEnum.Last;
84+
private int? LastNextValue { get; set; }
85+
private DaysMonthsEnum DaysMonthsOperator { get; set; } = DaysMonthsEnum.Days;
86+
87+
private async Task LastNextOperatorChanged(LastNextEnum newValue, FilterCellTemplateContext context)
88+
{
89+
LastNextOperator = newValue;
90+
await OnCustomDateFilterChanged(context);
91+
}
92+
93+
private async Task LastNextValueChanged(int? newValue, FilterCellTemplateContext context)
94+
{
95+
LastNextValue = newValue;
96+
await OnCustomDateFilterChanged(context);
97+
}
98+
99+
private async Task DaysMonthsOperatorChanged(DaysMonthsEnum newValue, FilterCellTemplateContext context)
100+
{
101+
DaysMonthsOperator = newValue;
102+
await OnCustomDateFilterChanged(context);
103+
}
104+
105+
private async Task OnLastNextClear(FilterCellTemplateContext context)
106+
{
107+
LastNextValue = default;
108+
await context.ClearFilterAsync();
109+
}
110+
111+
private async Task OnCustomDateFilterChanged(FilterCellTemplateContext context)
112+
{
113+
if (LastNextValue.HasValue)
114+
{
115+
context.FilterDescriptor.LogicalOperator = FilterCompositionLogicalOperator.And;
116+
context.FilterDescriptor.FilterDescriptors.Clear();
117+
context.FilterDescriptor.FilterDescriptors.Add(new FilterDescriptor()
118+
{
119+
Member = nameof(Order.DeliveryDate),
120+
Operator = FilterOperator.IsGreaterThanOrEqualTo,
121+
Value = LastNextOperator == LastNextEnum.Last
122+
? (DaysMonthsOperator == DaysMonthsEnum.Days ? DateTime.Today.AddDays(-LastNextValue.Value) : DateTime.Today.AddMonths(-LastNextValue.Value))
123+
: DateTime.Today
124+
});
125+
context.FilterDescriptor.FilterDescriptors.Add(new FilterDescriptor()
126+
{
127+
Member = nameof(Order.DeliveryDate),
128+
Operator = FilterOperator.IsLessThanOrEqualTo,
129+
Value = LastNextOperator == LastNextEnum.Last
130+
? DateTime.Today
131+
: (DaysMonthsOperator == DaysMonthsEnum.Days ? DateTime.Today.AddDays(LastNextValue.Value) : DateTime.Today.AddMonths(LastNextValue.Value))
132+
});
133+
134+
await context.FilterAsync();
135+
}
136+
else
137+
{
138+
await context.ClearFilterAsync();
139+
}
140+
}
141+
142+
protected override void OnInitialized()
143+
{
144+
Random rnd = Random.Shared;
145+
int halfCount = 100;
146+
147+
for (int i = 1; i <= halfCount * 2; i++)
148+
{
149+
GridData.Add(new Order()
150+
{
151+
Id = i,
152+
Customer = $"Customer {i} {(char)rnd.Next(65, 91)}{(char)rnd.Next(65, 91)}",
153+
Product = $"Product {i % 7 + 1}",
154+
Price = rnd.Next(1, 100) * 1.23m,
155+
Quantity = rnd.Next(0, 100),
156+
DeliveryDate = DateTime.Today.AddDays(-halfCount + i - 1)
157+
});
158+
}
159+
}
160+
161+
public class Order
162+
{
163+
public int Id { get; set; }
164+
public string Customer { get; set; } = string.Empty;
165+
public string Product { get; set; } = string.Empty;
166+
public decimal Price { get; set; }
167+
public int Quantity { get; set; }
168+
public DateTime DeliveryDate { get; set; }
169+
}
170+
171+
private enum LastNextEnum
172+
{
173+
Last,
174+
Next
175+
}
176+
177+
private enum DaysMonthsEnum
178+
{
179+
Days,
180+
Months
181+
}
182+
}
183+
````
184+
185+
## Notes
186+
187+
You can implement a similar UX outside the Grid filter templates, for example, in the [Grid ToolBar](slug:components/grid/features/toolbar). In that case, use the [Grid state methods](slug:grid-state#methods) to retrieve the [current filter descriptors](slug:grid-state#information-in-the-grid-state) and then update or remove them.
188+
189+
## See Also
190+
191+
* [Grid Filtering Overview](slug:components/grid/filtering)
192+
* [Grid Filter Templates](slug:grid-templates-filter)

0 commit comments

Comments
 (0)