在我的应用程序中,我有一个部分允许用户为搜索条件添加过滤器,该过滤器是一个可观察的数组,其中包含 3 个下拉菜单和用于手动添加值的输入字段。其中两个下拉菜单是静态的,第三个是根据页面中其他位置的选定项目填充的。我遇到麻烦的地方是两个数组之间的绑定。我填充了所有下拉列表,但我无法弄清楚如何传递 SelectedAttributes() 数组中的值以插入到我的过滤器列表的属性属性中
html
<input type="button" value="Add Filter" title="Add Filter" data-bind="click: $root.addFilter, enable: myfilters().length < 10" />
<table>
<tbody data-bind="foreach: myfilters">
<tr>
<td>
<!-- ko with: $root.iqReport -->
<select data-bind="options: SelectedAttributes(), optionsText: function(SelectedAttributes){ return SelectedAttributes.NameHierarchy() + '.' + SelectedAttributes.LabelName() }, optionsCaption:'Select a Field...'">
</select>
<!-- /ko -->
</td>
<td>
<select data-bind="options: $root.filterOperators, value:operator, optionsText: 'operatorName'">
</select>
</td>
<td>
<input data-bind="value: criteria1" />
</td>
<td>
<input data-bind="value: criteria2" />
</td>
<td>
<select data-bind="options: $root.joinOperators, value:joinOperator, optionsText: 'joinName'">
</select>
</td>
<td>
<a class="attributeLink" data-bind="click: $root.removeFilter">Remove</a>
</td>
</tr>
淘汰赛JS
function FilterList(JoiningOperator, AttributeHierarchy, AttributeIDHierarchy, Operator, FilterCriteria, FilterCriteriaRange) {
var self = this;
self.joinOperator = ko.observable(JoiningOperator);
self.attribute = ko.observable(AttributeHierarchy);
self.attributeID = ko.observable(AttributeIDHierarchy);
self.operator = ko.observable(Operator);
self.criteria1 = ko.observable(FilterCriteria);
self.criteria2 = ko.observable(FilterCriteriaRange);
}
var viewmodel function(){
//non-editable operators
self.filterOperators = [
{ operatorName: "EQUALS", operatorValue: "=" },
{ operatorName: "GREATER THAN", operatorValue: ">" },
{ operatorName: "GREATER THAN OR EQUAL TO", operatorValue: ">=" },
{ operatorName: "LESS THAN", operatorValue: "<" },
{ operatorName: "LESS THAN OR EQUAL TO", operatorValue: "<=" },
{ operatorName: "NOT EQUAL TO", operatorValue: "<>" },
{ operatorName: "NOT LESS THAN", operatorValue: "!>" },
{ operatorName: "NOT GREATER THAN", operatorValue: "!<" },
{ operatorName: "BETWEEN", operatorValue: "BETWEEN" },
{ operatorName: "LIKE", operatorValue: "LIKE" }
];
//non-editable joins
self.joinOperators = [
{joinName: "AND"},
{joinName: "OR"}
];
//define filter collection
self.myfilters = ko.observableArray([]);
//add new filter row
self.addFilter = function () {
self.myfilters.push(new FilterList(self.joinOperators[0], "", "", self.filterOperators[0], "", ""));
};
FilterList.attribute.subscribe(function () {
}, FilterList);
self.removeFilter = function (row) {
self.myfilters.remove(row);
};
}
集合 iqReports 是从另一个独立于 myfilters[] 的数组填充的,因此是 html 中的虚拟绑定。
我想了解的是,当用户从 Selected attributes 下拉列表中选择一个值时,我该如何让该值填充/更新self.attribute
myfilters的 observable 属性
更新
iqReports 集合是一个由其他可观察数组组成的可观察数组。这是在服务器端创建的,然后传回客户端。SelectedAttributes 类包含以下属性
public class ReportEntity
{
public int EntityId { get; set;
public string Name { get; set; }
public string IconPath { get; set; }
public List<ReportAttribute> PrimaryAttributes { get; set; }
public List<ReportAttribute> SecondaryAttributes { get; set; }
public List<ReportAssociatedEntity> AssociatedEntities { get; set; }
public string Hierarchy { get; set; }
public string NameHierarchy { get; set; }
public ReportEntity()
{
// Initialize the attributes lists.
PrimaryAttributes = new List<ReportAttribute>();
SecondaryAttributes = new List<ReportAttribute>();
// Initialize Associated Entities list.
AssociatedEntities = new List<ReportAssociatedEntity>();
}
}
public class ReportAttribute
{
public string FieldName { get; set; }
public string LabelName { get; set; }
public bool IsPrimary { get; set; }
public int Position { get; set; }
public bool IsSelected { get; set; }
public bool IsSortedBy { get; set; }
public int SortPosition { get; set; }
public bool SortAscending { get; set; }
public bool IsGroupedBy { get; set; }
public string NameHierarchy { get; set; }
public string Hierarchy { get; set; }
public ReportAttribute() { }
}
self.iqReport().SelectedAttributes()[0]().FieldName
回到客户端后,您可以使用Firebug以这种方式导航到值这与 iqReports 相关。删除 with 语句会破坏 foreach,因为它无法解析属性 SelectedAttributes() 尝试使用 $root 显式路径它不起作用,导致没有填充任何下拉列表。Firebug 此时会声明它找不到该属性SelectedAttributes().
我介绍的解决方法是将 iqReports 引用移出 foreach 所以我现在在 html 中有这个
<!-- ko with: $root.iqReport -->
<select data-bind="options: SelectedAttributes(), value: $root.selectedItem, optionsText: function(SelectedAttributes){ return SelectedAttributes.NameHierarchy() + '.' + SelectedAttributes.LabelName() }, optionsCaption:'Select a Field...'">
</select>
<!-- /ko -->
<input type="button" value="Add Filter" title="Add Filter" data-bind="click: $root.addFilter, enable: myfilters().length < 10" />
<!--<pre data-bind="text: ko.toJSON(iqReport, null, 2)"></pre>-->
<table>
<tbody data-bind="foreach: myfilters">
<tr>
<td>
<b><span data-bind="text: filterattribute" /></b>
</td>
<td>
<select data-bind="options: $root.filterOperators, value:operator, optionsText: 'operatorName'">
</select>
</td>
<td>
<input data-bind="value: criteria1" />
</td>
<td>
<input data-bind="value: criteria2" />
</td>
<td>
<select data-bind="options: $root.joinOperators, value:joinOperator, optionsText: 'joinName'">
</select>
</td>
<td>
<a class="attributeLink" data-bind="click: $root.removeFilter">Remove</a>
</td>
</tr>
</tbody>
</table>
然后在视图模型中,我添加了一个新的 observable 并为表设置映射,如下所示
self.selectedItem = ko.observable();
//define filter collection
self.myfilters = ko.observableArray([]);
//add new filter row
//Here I navigated to the individual field properties using the selectedItem object
self.addFilter = function () {
self.myfilters.push(new FilterList(self.joinOperators[0], self.selectedItem().NameHierarchy() + "." + self.selectedItem().FieldName(), "", self.filterOperators[0], "", ""));
};
虽然这不是我最初的首选方法,但这确实提供了一种解决方法。使用虚拟绑定允许我填充 select 元素,但我永远无法将该 select 的值传递回 myfilters.attribute() observable。我怀疑这是由于 foreach 但我不知道如何解决它
-干杯