当前位置: 首页 > 使用教程

UI组件库Kendo UI for Angular入门指南 – 从代码中动态过滤网格

发布时间:2023-02-07

Kendo UI致力于新的开发,来满足不断变化的需求。Kendo UI for Angular是Kendo UI系列商业产品的最新产品。Kendo UI for Angular是专用于Angular开发的专业级Angular组件。telerik致力于提供纯粹的高性能Angular UI组件,无需任何jQuery依赖关系。

虽然Kendo UI for Angular网格带有内置的过滤功能,但开发者有时需要允许用户控制过滤器显示的内容。

在本文中,我们将看到一个现实的示例,如何将过滤集成到应用程序中,以便当用户与应用程序的UI交付时,代码可以控制Grid(网格)显示哪些行。

Kendo UI R3 2022正式版下载

Telerik_KendoUI产品技术交流群:726377843    欢迎一起进群讨论

我们的案例研究应用程序相对简单:有一个显示客户列表和国家下拉列表的Grid,当用户从下拉列表中选择一个国家时,代码将更新Grid来只显示该国家的客户。同时还将添加一个复选框,允许用户根据客户是否加入公司的忠诚度计划来选择客户,下面是UI的样子:

UI组件库Kendo UI for Angular入门指南 - 从代码中动态过滤网格
定义UI

这个网格显示的Customer类有六个属性,然而对于这个案例研究,只对国家和inLoyaltyProgram属性感兴趣:

export class Customer
{
constructor(
public id: number,
public country: string,
public inLoyaltyProgram: Boolean,
public custName: string,
public signUpDate: Date | null,
public amountPurchased: number
) { }
}

定义下拉列表和复选框的标记看起来像这样:

Select Country:
<kendo-dropdownlist
[data]="countries"
defaultItem=”Pick a Country”
(selectionChange)="CountryChange($event)">
</kendo-dropdownlist><br/><br/>
Loyalty Program Only:  
<input type="checkbox" #loyalty kendoCheckBox
(change)="LoyaltyChange($event)"/>

这些组件中的每一个都调用一个函数,并在用户更改组件的值时传递相关的事件对象。我将把这两个函数(CountryChange用于下拉列表,LoyaltyChange用于复选框)称为“过滤器函数”。

还需要两个客户数组,第一个数组是客户的“完整/未过滤”数组(可能从某些Web服务获取),但是我们将Grid绑定到第二个名为selectCustomers的数组,该数组显示当前选定的客户。最初我们是希望两个数组是相同的,所以我像这样初始化数组:

public customers: Customer[];
public selectCustomers: Customer[] = [];

this.customers = [new Customer(1, "Peter Vogel", "USA", new Date(), 3250, true),
…more Customers…
];
this.selectCustomers = this.customers;

最后用kendo-Grid组件定义Grid,并将Grid绑定到selectCustomers列表。同时还定义了Grid中的每一列,以便可以将每一列绑定到公司的一个属性,控制列中的数据格式,在列的顶部设置标题,并指定列的宽度。

所有的Grid标记看起来像这样:

<kendo-Grid
[kendoGridBinding]="selectCustomers"
[height]="250"
(filterChange)= "this.filterCustomers($event)">
<kendo-Grid-column title="Id" field="id" [width]="50"></kendo-Grid-column>
<kendo-Grid-column title="Name" field="custName" [width]="150"></kendo-Grid-column>
<kendo-Grid-column title="Purchase" field="amountPurchased" [width]="125" format="99,999"></kendo-Grid-column>
<kendo-Grid-column title="Signed Up" field="signUpDate" [width]="200" format="MMM-dd-yyyy"></kendo-Grid-column>
<kendo-Grid-column title="In Program" field="inLoyaltyProgram" [width]="100"></kendo-Grid-column>
</kendo-Grid>
过滤的基础设施

要过滤一个网格,需要一个CompositeFilterDescriptor,它包含0个或多个FilterDescriptors(如果CompositeFilterDescriptor没有FilterDescriptors,那么没有行被“过滤掉”)。我们需要导入这两个类,因为稍后还需要filterBy函数,所以也将导入它:

import { CompositeFilterDescriptor, FilterDescriptor, filterBy }
from "@progress/kendo-data-query";

FilterDescriptor有三个属性对这个案例研究很重要:

  • field:要筛选的属性名称
  • operator:要使用的比较运算符(例如,eq, neq, gt等)
  • value:要比较的值

将两个filterdescriptor设置为属性是有意义的,一个用于按客户筛选,一个用于按忠诚度计划筛选,这可以将每个FilterDescriptor上的所有属性设置为一些默认值。这可以简化后面的代码:当用户在下拉列表和复选框中进行更改时,两个过滤器函数中唯一需要更改的属性是每个FilterDescriptor的value属性。

这两个FilterDescriptor属性的声明如下:

countryFilter: FilterDescriptor = {field:"country", operator:"eq", value:"Pick a country"};
loyaltyFilter: FilterDescriptor = {field:"inLoyaltyProgram", operator:"eq", value:false};

现在在过滤器函数中,只是从传递给函数的事件中检索当前值,并在适当的FilterDescriptor中设置value属性。这对于下拉列表来说非常简单,因为下拉列表的选择事件只是传递当前在下拉列表中选择的值:

CountryChange(e:string): void
{
this.countryFilter.value = e;
this.CreateFilter();
}

对于复选框来说有点复杂,因为该函数传递的是一个Event对象。然而,可以将事件对象的目标属性转换为HtmlInput对象,然后检索元素的checked属性来设置FieldDescriptor的value属性:

LoyaltyChange(e:Event): void
{
const cbx = e.target as HTMLInputElement;
this.loyaltyFilter.value = cbx.checked;
this.CreateFilter();
}

在每个函数末尾调用的CreateFilter函数将两个FilterDescriptors组装成一个CompositeFilter,并实际过滤数据(您将在接下来的短暂中断后看到该函数)。

用户体验中断

我们只给了用户筛选客户是否在忠诚度计划中的功能——用户不能筛选不在计划中的客户,这是因为在用户界面中使用了一个复选框来控制这个过滤选项。

虽然Kendo UI下拉列表有一个“不确定”的状态,允许复选框表明它还没有被触摸,一旦用户选中复选框,复选框只在true和false状态之间交替。如果我使用false将列表过滤到那些不在忠诚度计划中的客户,那么一旦用户选中复选框,用户将被限制在使用true查看计划中的客户和使用false查看计划中没有的客户之间切换,但不会是所有客户。

如果想让用户可以选择忠诚度计划过滤器的三种状态(在忠诚度计划中,不在忠诚度计划中,并且“不关心忠诚度计划”),我们将不得不使用一些其他组件组合(可能是两个单选按钮或另一个下拉列表)。

过滤客户

现在已经构建了FilterDescriptors,将它们组合在CreateFilter方法中。

在CreateFilter函数中,检查了两个FilterConditions中四个可能的值组合,并使用它们来加载CompositeFilterDescriptor的Filters数组:

  • 如果LoyaltyFilter设置为false, CustomerFilter设置为下拉列表的默认值,就不设置任何过滤器。
  • 如果LoyaltyFilter设置为true, CustomerFilter设置为某些国家(即,不是默认值),加载两个过滤器。
  • 对于任何其他组合,只加载具有其值集的筛选器。

当Filters条件中确实有多个项时,必须将CompositeFilterDescriptor的逻辑属性设置为” and “或” or “,以指示如何组合过滤器。当使用两个过滤器时,希望它们是“and”一起的,所以在CompositeFilterDescriptor中已经将逻辑属性设置为“and”。

在只有一个(或没有)过滤器的情况下,将逻辑属性设置为什么并不重要——将属性设置为” and “就可以了。

下面是构建ComponsiteFilterDescriptor的代码(可能有更复杂的方法,但这个版本的优势是显而易见的):

GridFilter:CompositeFilterDescriptor = {filters:[],logic:"and"};
CreateFilter()
{
if (!this.loyaltyFilter.value && this.countryFilter.value == "Pick a country")
{
this.GridFilter.filters = [];
}
if (!this.loyaltyFilter.value && this.countryFilter.value != "Pick a country")
{
this.GridFilter.filters = [this.countryFilter];
}
if (this.loyaltyFilter.value && this.countryFilter.value == "Pick a country")
{
this.GridFilter.filters = [this.loyaltyFilter];
}
if (this.loyaltyFilter.value && this.countryFilter.value != "Pick a country")
{
this.GridFilter.filters = [this.loyaltyFilter, this.countryFilter];
}

在CreateFilter函数的末尾,终于可以将完整的客户数组过滤到Grid所绑定的selectCustomers数组中。为此,使用前面导入的filterBy函数,传递完整的customers数组和CompositeFilterDescriptor,使用调用filterBy的结果来设置Grid绑定到的数组的代码如下所示:

…
{
this.GridFilter.filters = [this.loyaltyFilter, this.countryFilter];
}
this.selectCustomers = filterBy(this.customers, this.GridFilter);
}

现在,当用户与应用程序UI的其他部分交互时,代码将控制Grid显示的行。


了解最新Kendo UI最新资讯,请关注Telerik中文网!

扫码咨询
电话咨询
023-68661681
返回
顶部