2

私のアプリ内には、ユーザーが検索基準のフィルターを追加できるセクションがあります。フィルターは、手動で値を追加するための 3 つのドロップダウン メニューと入力フィールドを含む監視可能な配列です。ドロップダウン メニューのうち 2 つは静的で、3 つ目はページ内の他の場所にある選択された項目に基づいて入力されます。私が問題を抱えているのは、2 つの配列間のバインディングです。すべてのドロップダウンが表示されていますが、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 で仮想バインディングが行われます。

私が知りたいのは、ユーザーが [選択された属性] ドロップダウンから値を選択したとき、その値self.attributeを myfilters の監視可能なプロパティに入力/更新する方法です。

アップデート

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() { }
    }

クライアントに戻ったら、この方法で Firebug を使用して値に移動できますself.iqReport().SelectedAttributes()[0]().FieldName。参照が失われているのは、参照が別の監視可能な配列 (myfilters) 内にネストされているためだと思います。そのため、仮想バインディングがセクションにラップされています。これは iqReports に関連しています。$root を使用して明示的にパスしようとしている SelectedAttributes() プロパティを解決できないため、with ステートメントを削除すると foreach が壊れます。この時点で 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>

次に、ビューモデル内に新しいオブザーバブルを追加し、次のようにテーブルのマッピングをセットアップしました

 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() オブザーバブルに戻すことはできませんでした。foreach が原因だと思われますが、回避する方法がわかりません

-乾杯

4

1 に答える 1