javascript 如何在两个日期之间定义 Kendo 网格列过滤器?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25060935/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to define a Kendo grid Column filter between two dates?
提问by MWinstead
In our application we want the filter on a date column to prompt the user for a start date and an end date, with the filter returning rows where the field in question falls between (or on) those two dates.
在我们的应用程序中,我们希望日期列上的过滤器提示用户输入开始日期和结束日期,过滤器返回相关字段落在这两个日期之间(或之内)的行。
Initial Approach
初始方法
Our initial approach was to restrict date types to use gte and lte operators, and add the "extra : true" filterable option on the column. This came close, but presented the following problems: A) Each date input could use either the gte (Start) or lte (End) operator, providing undesired flexibility and the option for the user to create a filter that would never return results, and B) Presented a logical comparison (And / Or) that we don't want.
我们最初的方法是限制日期类型使用 gte 和 lte 运算符,并在列上添加“extra : true”可过滤选项。这很接近,但存在以下问题:A) 每个日期输入都可以使用 gte(开始)或 lte(结束)运算符,提供了不希望的灵活性和用户创建永远不会返回结果的过滤器的选项,以及B) 提出了我们不想要的逻辑比较 (And / Or)。
Better Approach
更好的方法
This questionhas an answer by Matthew Erwin that gets us very close: it allows us to completely re-style the filter entirely, so we can present simply a Start Date input and an End date input. However, what I can't get working is associating the right filter operation with the right input (gte for the Start date, lte for the End date). My custom filter is as follows:
这个问题有 Matthew Erwin 的回答,让我们非常接近:它允许我们完全重新设计过滤器的样式,因此我们可以简单地呈现开始日期输入和结束日期输入。但是,我无法工作的是将正确的过滤器操作与正确的输入相关联(gte 表示开始日期,lte 表示结束日期)。我的自定义过滤器如下:
$scope.dateFilter = {
extra: true,
operators: {},
ui: function (element) {
var parent = element.parent();
while (parent.children().length > 1)
$(parent.children()[0]).remove();
parent.prepend(
"Start Date:<br/><span class=\"k-widget k-datepicker k-header\">" +
"<span class=\"k-picker-wrap k-state-default\">" +
"<input data-bind=\"value: filters[0].value\" class=\"k-input\" type=\"text\" data-role=\"datepicker\"" +
" style=\"width: 100%\" role=\"textbox\" aria-haspopup=\"true\" aria-expanded=\"false\" aria-disabled=\"false\" " +
" aria-readonly=\"false\" aria-label=\"Choose a date\">" +
"<span unselectable=\"on\" class=\"k-select\" role=\"button\">" +
"<span unselectable=\"on\" class=\"k-icon k-i-calendar\">select</span></span></span></span>" +
"<br/>End Date:<br/>" +
"<span class=\"k-widget k-datepicker k-header\"><span class=\"k-picker-wrap k-state-default\">" +
"<input data-bind=\"value: filters[1].value\" class=\"k-input\" type=\"text\" data-role=\"datepicker\"" +
" style=\"width: 100%\" role=\"textbox\" aria-haspopup=\"true\" aria-expanded=\"false\" " +
" aria-disabled=\"false\" aria-readonly=\"false\" aria-label=\"Choose a date\">" +
"<span unselectable=\"on\" class=\"k-select\" role=\"button\">" +
"<span unselectable=\"on\" class=\"k-icon k-i-calendar\">select</span></span></span></span>"
);
}
};
With this approach, the Odata filter option is generated for each of the dates, however it uses the eq Equal To operator, so no values are ever returned. We aren't building filters specifically on the data source.
使用这种方法,会为每个日期生成 Odata 过滤器选项,但它使用 eq Equal To 运算符,因此永远不会返回任何值。我们没有专门针对数据源构建过滤器。
Is there a simple way I can associate each of those date inputs with a specific filter operator? Is there a better way to approach this subject? It seems like filtering dates based on a Start - End range would be commonly desired.
有没有一种简单的方法可以将每个日期输入与特定的过滤器运算符相关联?有没有更好的方法来解决这个问题?似乎通常需要根据开始 - 结束范围过滤日期。
Other Details
其他详情
We are using AngularJS, and WebAPI with Odata.
我们正在使用 AngularJS 和带有 Odata 的 WebAPI。
回答by MWinstead
After working with Telerik, I came to an answer. The thread that I opened can be found here, but I'll also summarize in this answer.
与 Telerik 合作后,我得到了答案。我打开的线程可以在这里找到,但我也会在这个答案中进行总结。
The ultimate solution was to:
最终的解决方案是:
- Use the "Messages" option of the column "filterable" option to customize the filter display message.
- Use the "Extra" option of the column "filterable" option to get the extra Date selector in the filter menu.
- Configure the "Operators" option in the grid filterable option to set what operators can be used for dates (gte, lte) and what text is displayed for each (Begin Date, End Date).
- Use the filterMenuInit event to configure the filter controls.
- 使用列“可过滤”选项的“消息”选项自定义过滤器显示消息。
- 使用列“可过滤”选项的“额外”选项在过滤器菜单中获得额外的日期选择器。
- 配置网格可过滤选项中的“运算符”选项以设置可用于日期(gte、lte)的运算符以及为每个运算符显示的文本(开始日期、结束日期)。
- 使用 filterMenuInit 事件来配置过滤器控件。
End Result
最终结果
Column Filterable
列可过滤
The following filterable options were used:
使用了以下可过滤选项:
filterable: { "extra": "true", "messages": { "info": "Show items between dates:" }}
Extra gives us the second date selector, and the "info" message customizes the text displayed at the top of the filter menu.
Extra 为我们提供了第二个日期选择器,“信息”消息自定义显示在过滤器菜单顶部的文本。
Grid Filterable
网格可过滤
I used the "operators" option in the grid-level "filterable" option to make date filters only provide the gte and lte operators, and to customize the text for those operators. This is what the operators configuration object wound up looking like:
我在网格级别的“可过滤”选项中使用了“运算符”选项来使日期过滤器仅提供 gte 和 lte 运算符,并为这些运算符自定义文本。这就是运算符配置对象最终的样子:
"date": {
"gte": "Begin Date",
"lte": "End Date"
}
Because we want this to apply for all dates, we put that in a factory and reuse it in each angular controller / view.
因为我们希望它适用于所有日期,所以我们将它放在一个工厂中并在每个角度控制器/视图中重用它。
filterMenuInit Event
filterMenuInit 事件
By providing a handler for the filterMenuInit event, you can access and configure the individual controls in the filter menu as it is created. The handler function that I created looks like this:
通过为 filterMenuInit 事件提供处理程序,您可以在创建过滤器菜单时访问和配置过滤器菜单中的各个控件。我创建的处理程序函数如下所示:
function (e) {
if (e.sender.dataSource.options.schema.model.fields[e.field].type == "date") {
var beginOperator = e.container.find("[data-role=dropdownlist]:eq(0)").data("kendoDropDownList");
beginOperator.value("gte");
beginOperator.trigger("change");
beginOperator.readonly();
var logicOperator = e.container.find("[data-role=dropdownlist]:eq(1)").data("kendoDropDownList");
logicOperator.readonly();
var endOperator = e.container.find("[data-role=dropdownlist]:eq(2)").data("kendoDropDownList");
endOperator.value("lte");
endOperator.trigger("change");
beginOperator.readonly();
}
Specifically, for any date field, this function sets the first and last dropdown operators to "gte" and "lte" respectfully (Those are the dropdowns for the first date operator and the second date operator), and sets all of the dropdowns to read-only so the user can't change them (the only other dropdown, which is at index 1, is the logical comparison - only And makes sense, so we don't let users change it.)
具体来说,对于任何日期字段,此函数将第一个和最后一个下拉运算符分别设置为“gte”和“lte”(这些是第一个日期运算符和第二个日期运算符的下拉列表),并将所有下拉列表设置为读取- 只有这样用户才能更改它们(索引 1 处的唯一其他下拉列表是逻辑比较 - 只有 并且有意义,所以我们不让用户更改它。)
This function applies this configuration for any fields that are of "date" type. I did it this way so that I could create this function once, put it in an Angular factory, and then reuse it for any grid that I needed. If you don't want to apply this as a blanket configuration across all of your date columns, you can change the conditional to check for fields by name. Example:
此功能将此配置应用于任何“日期”类型的字段。我这样做是为了我可以创建一次这个函数,把它放在一个 Angular 工厂中,然后将它重用于我需要的任何网格。如果您不想将其应用为所有日期列的全面配置,您可以更改条件以按名称检查字段。例子:
if (e.field == "fieldName")
Hopefully this will be helpful to someone else. This doesn't give you ultimate customization of the UI in the filter menu, but it does let you simply set up a filter between two dates. I'm sure someone clever could merge this with my original strategy (replacing the markup for the filter menu entirely) to come up with something completely customized.
希望这对其他人有帮助。这不会让您在过滤器菜单中对 UI 进行最终自定义,但它确实让您可以简单地在两个日期之间设置过滤器。我相信聪明的人可以将其与我的原始策略(完全替换过滤器菜单的标记)合并,以提出完全自定义的内容。
回答by Murat Y?ld?z
You can try the following method that gives two option for filtering: With two filtering fields and with the grid column.
您可以尝试以下提供两种过滤选项的方法:使用两个过滤字段和使用网格列。
<div>
From: <input id="from" /> To: <input id="to" />
<br />
<br />
<button id="filter" class="k-button">Filter</button>
</div>
<br />
<br />
<div id="grid"></div>
<script>
var grid = $("#grid").kendoGrid({
dataSource: {
type: "json",
transport: {
read: "/Controller/Action"
},
pageSize: 10,
schema: {
model: {
fields: {
OrderId: { type: 'number' },
OrderItem: { type: 'string' },
OrderDate: { type: 'date' }
}
}
}
},
pageable: true,
filterable: true,
navigatable: true,
selectable: true,
columns:
[
{ field: "OrderID", width: 100, title: "Order ID", filterable: false },
{ field: "OrderItem", width: 100, title: "Order Item", filterable: false },
{
field: "OrderDate", type: "date", width: 125, title: "Order Date",
template: "#= kendo.toString(kendo.parseDate(EventTime, 'dd.MM.yyyy hh:mm tt'), 'dd.MM.yyyy hh:mm tt') #",
filterable: {
ui: "datetimepicker"
}
},
]
}).data("kendoGrid");
$("#from, #to").kendoDatePicker({
});
$("#filter").on("click", function () {
//var from = $("#from").data("kendoDatePicker").value();
//var to = $("#to").data("kendoDatePicker").value();
//If there is a problem regarding to the two lines above, you can also try this:
var from = $("#from").val();
var to = $("#to").val();
var filter = [
{ field: "OrderDate", operator: "gte", value: from },
{ field: "OrderDate", operator: "lte", value: to }
];
grid.dataSource.filter(filter);
});
</script>
For more information Date Range Filtering in Kendo Grid Using WEB API and Entity Framework.