2

在我的应用程序中,我有一个部分允许用户为搜索条件添加过滤器,该过滤器是一个可观察的数组,其中包含 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.attributemyfilters的 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 但我不知道如何解决它

-干杯

4

1 回答 1

1

使用value绑定并将其绑定到self.attribute,然后删除with绑定以便value绑定可以找到self.attribute

所以代替这个:

<!-- ko with: $root.iqReport -->
    <select data-bind="
        options: SelectedAttributes(), 
        optionsText: function(SelectedAttributes){ 
            return SelectedAttributes.NameHierarchy() + '.' + SelectedAttributes.LabelName() },
        optionsCaption:'Select a  Field...'
    ">
    </select>
<!-- /ko -->

做这个:

<select data-bind="
    options: $root.iqReport.SelectedAttributes(), 
    optionsText: function(SelectedAttributes){ 
        return SelectedAttributes.NameHierarchy() + '.' + SelectedAttributes.LabelName() 
    },  
    optionsCaption:'Select a Field...',
    value: attribute 
">
于 2013-05-20T03:01:37.880 回答