Knockoutの学習を開始しましたが、ボタンクリックで観測可能な配列をフィルタリングして結果を表示するのに問題があります。
これは私のモデルです:
function Product(data) {
this.id = data.id;
this.name = data.name;
this.price = data.price;
this.description = data.desc;
this.image = data.image;
this.genre = data.genre;
this.show = data.show;
this.offer_desc = data.offer_desc;
this.offer_id = data.offer_id;
}
function ProductModel() {
var self = this;
self.products = ko.observableArray([]);
$.getJSON('../PHP/Utilities.php?json=true', function(json) {
var mappedProducts = $.map(json, function(item) { return new Product(item) });
self.products(mappedProducts);
});
self.filterProducts = ko.computed(function(genre) {
if(typeof genre === 'undefined') {
return self.products(); //initial load when no genre filter is specified
} else {
return ko.utils.arrayFilter(self.products(), function(prod) {
return prod.genre = genre;
});
}
});
}
ko.applyBindings(new ProductModel());
これはhtmlです:
<div data-bind="foreach: filterProducts">
<div class="row">
<div class="col-md-2">
<img data-bind="attr:{src: '../images/' + image, alt: name}" />
</div>
<div class="col-md-2" data-bind="text: name"></div>
<div class="col-md-1" data-bind="text: price"></div>
<div class="col-md-3" data-bind="text: description"></div>
<div class="col-md-1" data-bind='text: offer_id'>
<div class="col-md-2" data-bind="text: genre"></div>
<div class="col-md-1" data-bind="text: show"></div>
</div>
</div>
また、クリック機能をバインドしてジャンルの製品をフィルタリングする方法もわかりません。私はこのようなことを考えました...しかし、それは動作しません
<button data-bind="click: filter('1')"> Filter </button>
self.filter = function(genre) {
self.filterProducts(genre);
}
_ko.computed
_内にパラメーターを持つ関数を作成することはできません。
必要なのは、現在のフィルターを新しいプロパティに保存し、それを計算で使用することです
_function ProductModel() {
var self = this;
self.products = ko.observableArray([]);
self.currentFilter = ko.observable(); // property to store the filter
//...
self.filterProducts = ko.computed(function() {
if(!self.currentFilter()) {
return self.products();
} else {
return ko.utils.arrayFilter(self.products(), function(prod) {
return prod.genre == self.currentFilter();
});
}
});
}
_
そして、click
ハンドラーで現在のフィルターを設定するだけです:
_<button data-bind="click: function() { filter('1') }"> Filter </button>
self.filter = function(genre) {
self.currentFilter(genre);
}
_
デモ JSFiddle
click
バインディングで追加の引数aを渡したい場合は、必要なfunction() { }
に注意してください( documentation も参照)。そうでない場合、Knockoutは関数を実行しますボタンをクリックしたときではなく、バインディングを解析します。
まず、computed Observables
。 KnockoutJSドキュメント から:
これらは、1つ以上の他のオブザーバブルに依存する関数であり、これらの依存関係のいずれかが変更されるたびに自動的に更新されます。
計算されたオブザーバブルfilterProducts
は、オブザーバブル配列products
に依存しますが、これは変化しません。値を読み取るだけです。したがって、filterProducts
を再評価するよう通知することはありません。
それでは、簡単な簡単な修正は何でしょうか?
filteredGenre
が依存する新しいオブザーバブルオブジェクトfilterProducts
を定義します。filterProducts
の値を確認し、それに基づいてフィルターされた製品を返すように、filteredGenre
を変更します。filter
関数を変更して、新しいgenre
を取得したときにfilteredGenre
を変更し、計算されたfilterProducts
を再評価するようにします。私はあなたがアイデアを得たことを願っています。
オリジナルのノックアウトの作者が作成した Knockout Projections プラグインをご覧ください。 大規模なコレクションを使用したシナリオでパフォーマンス上の利点があります。詳細については、 blogpost を参照してください。
self.filterProducts = self.products.filter(function(prod) {
return !self.currentFilter() || prod.genre == self.currentFilter();
});