私のアプリ内には、ユーザーが検索基準のフィルターを追加できるセクションがあります。フィルターは、手動で値を追加するための 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 が原因だと思われますが、回避する方法がわかりません
-乾杯