Kendo Grid拼接列(Client Template)过滤失效,求助自定义过滤方案
Hey there, I’ve run into this exact issue before—when you have a calculated column (like Name from FirstName + LastName) that isn’t a direct database field, the out-of-the-box .Filterable(true) won’t work because the grid doesn’t know how to map the filter to the actual underlying fields. Here are two solid approaches to fix this, depending on whether you’re using client-side or server-side data binding:
Option 1: Client-Side Filtering (Small Datasets)
If your dataset is small enough to load all records upfront, you can build a custom filter menu that targets both FirstName and LastName directly:
Step 1: Configure the Grid Column
Update your Name column definition to use a custom filter template instead of the default:
columns.Bound(p => p.Name) .Title("Full Name") .Filterable(filterable => filterable .Template("customNameFilterTemplate") // Reference our custom template .Operators(op => op.String(str => str.Clear() // Clean up default operators .Contains("Contains") .EqualTo("Exact Match"))));
Step 2: Define the Custom Filter Template
Add this script to your view to render a simple filter input with apply/clear buttons:
<script id="customNameFilterTemplate" type="text/x-kendo-template"> <div class="k-filter-menu p-3"> <label class="mb-2 d-block">Filter by Full Name:</label> <input type="text" class="k-input w-100 mb-2" id="nameFilterInput" placeholder="Enter name..." /> <div class="d-flex gap-2"> <button class="k-button k-primary" onclick="applyNameFilter()">Apply</button> <button class="k-button" onclick="clearNameFilter()">Clear</button> </div> </div> </script>
Step 3: Add Filter Logic with JavaScript
These functions will apply an OR filter to both FirstName and LastName when the user clicks "Apply":
function applyNameFilter() { const grid = $("#yourGridId").data("kendoGrid"); const filterValue = $("#nameFilterInput").val().trim(); if (filterValue) { // Create OR filter for FirstName and LastName const filter = { logic: "or", filters: [ { field: "FirstName", operator: "contains", value: filterValue }, { field: "LastName", operator: "contains", value: filterValue } ] }; grid.dataSource.filter(filter); } else { grid.dataSource.filter({}); // Clear all filters } } function clearNameFilter() { $("#nameFilterInput").val(""); applyNameFilter(); }
Option 2: Server-Side Filtering (Large Datasets/Pagination)
If you’re using server-side data operations (like Ajax binding with pagination), you need to intercept the filter request on the backend and map the Name filter to FirstName and LastName:
Step 1: Adjust the Grid Column (Same as Client-Side)
Keep the same column configuration from Option 1 so the grid sends the Name filter parameter to your controller.
Step 2: Modify the Read Action in Your Controller
Update your data retrieval action to rewrite the Name filter into an OR condition for the actual fields:
public ActionResult Grid_Read([DataSourceRequest] DataSourceRequest request) { // Rewrite any filters targeting the "Name" column if (request.Filters.Any()) { var adjustedFilters = new List<IFilterDescriptor>(); foreach (var filter in request.Filters) { if (filter is FilterDescriptor nameFilter && nameFilter.Member == "Name") { // Create OR filters for FirstName and LastName using the same operator/value var firstNameFilter = new FilterDescriptor("FirstName", nameFilter.Operator, nameFilter.Value); var lastNameFilter = new FilterDescriptor("LastName", nameFilter.Operator, nameFilter.Value); adjustedFilters.Add(new CompositeFilterDescriptor { Logic = FilterCompositionLogicalOperator.Or, FilterDescriptors = { firstNameFilter, lastNameFilter } }); } else { adjustedFilters.Add(filter); // Keep other filters as-is } } request.Filters = adjustedFilters; } // Fetch and return data with the adjusted filters var data = _yourDataService.GetAllRecords(); // Your data access logic var result = data.ToDataSourceResult(request); return Json(result); }
Bonus: Ensure the Calculated Name Field is Available
If you’re using server-side projection, make sure your data model includes the concatenated Name field so it’s returned to the grid:
public class PersonViewModel { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string Name => $"{FirstName} {LastName}"; // Calculated field }
Either approach should get your Name column filtering working perfectly. I’d recommend the server-side method if you’re dealing with large datasets to avoid loading all records upfront.
内容的提问来源于stack exchange,提问作者atul goenka

