使用 knockout.js 控制级联选择

分享于 

11分钟阅读

Web开发

  繁體

介绍

本文提供的源代码使你能够轻松配置包含用于筛选记录( 通常显示在网格或者表格中)的Collection的多个选择控件的网页。 在这个例子中,我们使用ficticious住宅地址的Collection 代表房租。 页面将允许用户按状态。城市。邮政编码。# 和住宅类型筛选这里列表。

页面依赖于 knockout.js 库提供的数据绑定。 这里绑定会导致选择用户的更改立即反映在其他控件中可用的选项中。 例如,如果用户在城市控制中选择,那么邮政编码控制只显示在费费尔的,。

请参见 FiddleJS
注意:功能是抽象的,因此它可以应用于任何类型的记录。 你只需要指定要过滤的属性的名称 !

背景

在过去,我在普通的javascript中反复实现这个功能。 这个工作很正常,但编码非常繁琐和劳动密集。 我最近开始使用 javascript libray Knockout,所以我决定看看Knockout是否能使问题更容易。

我使这个库变得灵活,因此:

1.heirarchical方式中可以链接任意数量的选择控件。 通过将属性 NAME 指定给要筛选的记录,并可选择对应于父控件的属性 NAME 来配置每个属性。

2.控件可以是拖放或者多选择列表框的混合。

3。控件可以是与父级和子级相关的heirarchically,或者它的中的某些可以独立于它的他级别。

4.控件是动态创建的,因此不需要硬编码每个控件。 这意味着页面可以配置为使用控件的变量集。

内部结构

所有的内部javascript代码都放在文件 SelectFilters.js 中。 这样可以方便地移植类。 应用程序中的多个网页可以引用这里文件。

在 SelectFilters.js 中,定义了两个类。 第一个是 sfViewModel 对象。 这是一个子模型,包含在页面本身定义的modelView 对象中。 所有挖空页面一样,页面控件中的数据绑定引用视图模型或者其中一个包含的对象的属性。

第二个类叫做 selectFilter。 每个选择控件创建一个 selectFilter 对象,并且选择控件使用Knockout数据绑定直接绑定到这里对象。 sfViewModel 有一个 selectFilter 对象的Collection。

用户使用选择控件之一进行选择时,通过在选择控件上定义的数据绑定属性向相应的selectFilter 对象发送消息:

<code><selectstyle="vertical-align:top"multipledata-bind="attr: { multiple:multiSelect}, options: availableValues, value: value, selectedOptions: values"></code>

这里对象依次调用 <span style="color: black; font-family: Consolas, 'Courier New', Courier, mono; font-size: 9pt; white-space: pre; background-color: rgb(251, 237, 187);"> sfViewModel.resolveSelections()</span><span style="color: black; font-family: Consolas, 'Courier New', Courier, mono; font-size: 9pt; white-space: pre; background-color: rgb(251, 237, 187);"> </span>.sfViewModel 依次遍历它的selectFilter 对象列表和调用 selectFilter.setAvailableOptions( ) 在其中,重新计算选项列表的位置。 选项列表( availableValues ) 是一个 ko.observableArray 并且数据绑定到控件的选择选项,则自动更新选项列表。

在调用 <span style="color: rgb(0, 0, 0); font-family: Consolas, 'Courier New', Courier, mono; font-size: 12px; white-space: pre; background-color: rgb(251, 237, 187);"> viewModel.resolveSelections() </span> 所有记录的列表都根据用户选择进行筛选。 在我们的页面中,数据绑定到页底部与数据绑定属性的table:

<code><tbodydata-bind="foreach: selectedItems"></code>

因为 viewModel.selectedItems 列表也是 ko.observableArray 显示的table 也会自动更新。 在这个函数中 activeFilters array 被更新,并且它也被绑定到表上方过滤值列表的数据。

文件

SelectFiltersExample.zip 中最重要的文件是:

  • SelectFiltersExample/Views/Home/Index.cshtml --主页的HTML。

  • SelectFiltersExample/Scripts/SelectFilters.js -- 2 javascript类和一个被称为 loadByProperties的自定义自定义函数。

  • SelectFiltersExample/Scripts/knockout-3.1.0.js --从 knockoutjs.com 下载的库。

任何人希望在其他环境中使用这个概念,比如 PHP,只需要从zip文件中获取第一个 2文件。

使用代码

你可以轻松地将包含的代码添加到你自己的项目中。 我选择在后端使用 ASP.NET MVC实现它,但是服务器平台的选择没有区别;它是javascript和html操作在后台的位置。 你可以在Linux服务器上使用这里代码,或者在。

要在这个项目中运行代码,要么打开MVC项目zip文件,然后在 Visual Studio 中加载一些代码。

要将这里功能添加到你自己的网页,你需要执行以下操作:

包含 <脚本( 包括脚本> 参考 knockout.js 库以及 SelectFilters.js 文件,就像这个项目的HTML文件的顶部。

将这个HTML插入到你的页面。

下面是选择控件的HTML。 表达式 <span style="color: black; font-family: Consolas, 'Courier New', Courier, mono; font-size: 9pt; white-space: pre; background-color: rgb(251, 237, 187);"> data-bind="foreach: selectFilters" </span> 使内容成为 inside <> 对视图列表中的每个 selectFilter 对象重复一次。

<code><!-- SELECT controls from the viewModel.selectFilters collection --><pdata-bind="foreach: selectFilterVM.selectFilters"></code><code><spanstyle="font-weight: bold; vertical-align: top"data-bind="text: nameLabel"></span><selectstyle="vertical-align: top"data-bind="attr: { multiple: multiSelect },
 options: availableValues,
 value: value,
 selectedOptions: values"></select></code></p>

below 是当前应用的过滤器的可选列表的HTML,它的"清除"链接为:

<code><!-- list the currently active filter values --><uldata-bind="foreach: selectFilterVM.activeFilters"><li><spanstyle="font-weight:bold"data-bind="text: nameLabel"></span><spandata-bind="text: valueText"></span>&nbsp;<ahref="#"data-bind="event:{ click: reset }">clear</a></li></ul></code>

服务器端的,提供了一种下载记录的方法。 对于我的MVC项目,我使用了一个jQuery调用,它在 ready() 函数中返回 JSON:

<code> $.getJSON("/Home/GetHomes", model.loadData(model)); </code>

代码页中的修改代码以加载过滤器,指示希望用户筛选的记录属性,以及哪些控件是其他控件的父记录。 下面是示例:

<code> // Define the filtering select controls this way.// Parameters to selectFilter() are:// name: name of property to filter on// parentName: name of master select control's property// model: the model object for this view// multiselect: whether to allow selection of multiple valuesfunction loadSelects(model) {
 new selectFilter('State', '', model, 'state', true);
 new selectFilter('City', 'State', model, 'city', false);new selectFilter('Zip', 'City', model, 'Zip code', true);
 new selectFilter('BRs', 'Zip', model, '# of bedrooms', true);
 new selectFilter('HomeType', 'BRs', model, 'home type', true);
 }</code>

例如第二个 selectFilter() 调用创建一个与'城市'select控件对应的javascript selectFilter 对象:

<code>new selectFilter('City', 'State', model, 'city', false);</code>

第二个参数匹配传递给第一个 selectFilter,'状态'的名称,因此它的父选择控件是'状态'列表框。

第三个参数是视图模型参考。

第四个参数提供一个标签值以显示给用户。 你可以根据语言等改变这一点。

第五个参数表示 multiselect=false,因此它将显示为下拉框而不是列表框。

也可以从服务器下载这些参数列表,动态定义选择控件。 确保下载数据记录中的第一个和第二个参数 MATCH 属性名。

摘要

如下面的代码一样,在一些构造函数调用中更改父级的NAME,观察页面的行为。 你还可以将最后一个参数从 true 更改为 false。

我希望任何反馈 ! 我非常新新,我也不是javascript的最大专家,因这里我相信有一些提高这种代码的好建议。

历史记录

年:月: 初始版本

年:月: 为了在同一页面上与其他的Knockout模型对象和绑定共存,我将modelView类重命名为 sub,使它成为一个子模型,而不是页面的主视图。 我把那个类改名为 fsViewModel。 现在在页面iteslf上添加了一个新的viewModel 对象,它具有名为 selectFilterVM的属性,它是包含过滤器选择的fsViewModel。 对数据绑定中的veiwmodel属性的所有引用现在都有前缀 selectFilterFM。


相关文章