Skip to content

Commit c885cb7

Browse files
authored
docs(grid): Fix bug in custom checkbox filtering example (#1070)
CheckedItems is not updated when the user clicks on the Clear button.
1 parent ea53661 commit c885cb7

File tree

1 file changed

+44
-66
lines changed

1 file changed

+44
-66
lines changed

components/grid/templates/filter.md

+44-66
Original file line numberDiff line numberDiff line change
@@ -196,37 +196,28 @@ For an example with the CheckboxList Filter, see the [Custom Data]({%slug grid-c
196196
````CSHTML
197197
@using Telerik.DataSource
198198
199-
This custom filter menu lets you choose more than one option to match against the data source
200-
201-
<TelerikGrid Data=@GridData FilterMode="@GridFilterMode.FilterMenu"
202-
Height="400px" Width="600px" Pageable="true">
199+
<TelerikGrid Data="@GridData"
200+
FilterMode="@GridFilterMode.FilterMenu"
201+
Pageable="true"
202+
Width="600px">
203203
<GridColumns>
204-
<GridColumn Field="Id" Filterable="false" Width="80px" />
205-
206-
<GridColumn Field="Size">
204+
<GridColumn Field="@(nameof(Product.Name))" Title="Product" Filterable="false" />
205+
<GridColumn Field="@(nameof(Product.Size))">
207206
<FilterMenuTemplate>
208-
@{
209-
// we store a reference to the filter context to use in the business logic to show we can
210-
// we could, alternatively pass it as an argument to the event handler in the lambda expression
211-
// which can be useful if you want to use the same filter for several columns
212-
// you could then pass more arguments to the business logic such as field name and so on
213-
theFilterContext = context;
214-
}
215-
216207
@foreach (var size in Sizes)
217208
{
218209
<div>
219210
<TelerikCheckBox Value="@(IsCheckboxInCurrentFilter(context.FilterDescriptor, size))"
220211
TValue="bool"
221-
ValueChanged="@((value) => UpdateCheckedSizes(value, size))"
212+
ValueChanged="@((value) => UpdateCheckedSizes(value, size, context))"
222213
Id="@($"size_{size}")">
223214
</TelerikCheckBox>
224215
<label for="@($"size_{size}")">
225216
@if (size == null) // part of handling nulls - show meaningful text for the end user
226217
{
227218
<text>Empty</text>
228219
}
229-
else
220+
else
230221
{
231222
@size
232223
}
@@ -235,16 +226,11 @@ This custom filter menu lets you choose more than one option to match against th
235226
}
236227
</FilterMenuTemplate>
237228
</GridColumn>
238-
239-
<GridColumn Field="ProductName" Title="Product" Filterable="false" />
240229
</GridColumns>
241230
</TelerikGrid>
242231
243232
@code {
244-
FilterMenuTemplateContext theFilterContext { get; set; }
245-
public List<string> CheckedSizes { get; set; } = new List<string>();
246-
247-
public bool IsCheckboxInCurrentFilter(CompositeFilterDescriptor filterDescriptor, string size)
233+
private bool IsCheckboxInCurrentFilter(CompositeFilterDescriptor filterDescriptor, string size)
248234
{
249235
// get all current filter descriptors and evaluate whether to select the current checkbox
250236
// the default value for string filter descriptors is null so it would select the null checkbox always
@@ -253,7 +239,7 @@ This custom filter menu lets you choose more than one option to match against th
253239
{
254240
foreach (FilterDescriptor item in filterDescriptor.FilterDescriptors)
255241
{
256-
if(item.Operator == FilterOperator.IsNull)
242+
if (item.Operator == FilterOperator.IsNull)
257243
{
258244
return true;
259245
}
@@ -263,71 +249,63 @@ This custom filter menu lets you choose more than one option to match against th
263249
return filterDescriptor.FilterDescriptors.Select(f => (f as FilterDescriptor).Value?.ToString()).ToList().Contains(size);
264250
}
265251
266-
public void UpdateCheckedSizes(bool value, string itemValue)
252+
private void UpdateCheckedSizes(bool isChecked, string itemValue, FilterMenuTemplateContext context)
267253
{
268-
// update the list of items we want to filter by
269-
var isSizeChecked = CheckedSizes.Contains(itemValue);
270-
if (value && !isSizeChecked)
271-
{
272-
CheckedSizes.Add(itemValue);
273-
}
254+
var compositeFilterDescriptor = context.FilterDescriptor;
255+
compositeFilterDescriptor.LogicalOperator = FilterCompositionLogicalOperator.Or;
274256
275-
if (!value && isSizeChecked)
257+
if (!isChecked)
276258
{
277-
CheckedSizes.Remove(itemValue);
278-
}
279-
280-
// prepare filter descriptor
281-
var filterDescriptor = theFilterContext.FilterDescriptor;
282-
283-
filterDescriptor.FilterDescriptors.Clear();
284-
// use the OR logical operator so we include all possible values
285-
filterDescriptor.LogicalOperator = FilterCompositionLogicalOperator.Or;
286-
CheckedSizes.ForEach(s => {
287-
// instantiate a filter descriptor for the desired field, and with the desired operator and value
288-
FilterDescriptor fd = new FilterDescriptor("Size", FilterOperator.IsEqualTo, s);
289-
// set its type to the field type you filter (the Size field in this example)
290-
fd.MemberType = typeof(string);
291-
// handle null values - use a specific filter operator that the user cannot select on their own
292-
// in this custom filter template (the grid has it in a dropdown by default)
293-
if(s == null)
259+
// find and remove the filter descriptor for this checkbox
260+
compositeFilterDescriptor.FilterDescriptors.Remove(compositeFilterDescriptor.FilterDescriptors.First(x =>
294261
{
295-
fd.Operator = FilterOperator.IsNull;
296-
}
297-
298-
filterDescriptor.FilterDescriptors.Add(fd);
299-
});
300-
301-
//ensure there is at least one blank filter to avoid null reference exceptions
302-
if (!filterDescriptor.FilterDescriptors.Any())
262+
var fd = x as FilterDescriptor;
263+
if ((fd.Operator == FilterOperator.IsNull && itemValue == null) ||
264+
(fd.Operator == FilterOperator.IsEqualTo && fd.Value?.ToString() == itemValue))
265+
{
266+
return true;
267+
}
268+
else
269+
{
270+
return false;
271+
}
272+
}));
273+
}
274+
else
303275
{
304-
filterDescriptor.FilterDescriptors.Add(new FilterDescriptor());
276+
// add a filter descriptor for this checkbox
277+
compositeFilterDescriptor.FilterDescriptors.Add(new FilterDescriptor()
278+
{
279+
Member = nameof(Product.Size),
280+
MemberType = typeof(string),
281+
Operator = itemValue == null ? FilterOperator.IsNull : FilterOperator.IsEqualTo,
282+
Value = itemValue
283+
});
305284
}
306285
}
307286
308-
// sample grid data
287+
private List<Product> GridData { get; set; }
309288
310-
public List<SampleData> GridData { get; set; }
289+
private string[] Sizes = new string[] { "XS", "S", "M", "L", "XL", null };
311290
312291
protected override void OnInitialized()
313292
{
314-
GridData = Enumerable.Range(1, 70).Select(x => new SampleData
293+
GridData = Enumerable.Range(1, 70).Select(x => new Product
315294
{
316295
Id = x,
317296
Size = Sizes[x % Sizes.Length],
318-
ProductName = $"Product {x}"
297+
Name = $"Product {x}"
319298
}).ToList();
299+
320300
base.OnInitialized();
321301
}
322302
323-
public class SampleData
303+
public class Product
324304
{
325305
public int Id { get; set; }
306+
public string Name { get; set; }
326307
public string Size { get; set; }
327-
public string ProductName { get; set; }
328308
}
329-
330-
public string[] Sizes = new string[] { "XS", "S", "M", "L", "XL", null };
331309
}
332310
````
333311

0 commit comments

Comments
 (0)