如何使用淘汰数据和"外部"来过滤数据。数据

时间:2015-03-05 09:58:21

标签: javascript knockout.js

背景:我正在将遗留系统中的javascript逻辑转移到淘汰赛以获得更多结构,并且将来必须编写更少的代码。由于时间限制,我只能将部分代码移到每次部署之间进行淘汰。

问题:部分数据是由遗留代码生成的,有些数据是由淘汰生成的,而且我在创建淘汰逻辑时遇到问题需要处理以下情况(见下文)代码片段和JSFiddle链接到相同的代码)。产品单选按钮不是由淘汰产生的,但是产品列表是。过滤商品列表的关键按钮就像我想要的那样,但我已经设法弄清楚如何仅获得产品1 下列出的产品1的优惠,而且只提供产品2列在产品2 下。有人可以提供帮助吗?

我认为如果产品标题是根据淘汰视图模型中的数据生成的,那么我的问题就不会那么难以解决,但正如您所看到的那样,并非如此。

https://jsfiddle.net/b6er4wke/3/



function myViewModel() {
    var self = this;
    self.wrappedProducts = ko.observableArray();
    self.availableOffers = ko.observableArray();
    self.filterKey = ko.observable(1);
    filteredItems = ko.computed(function() {
        return ko.utils.arrayFilter(self.availableOffers(), function (offer) {
            var isCorrectKey = offer.key == self.filterKey();
            return (isCorrectKey);
        });
    });
    
    self.filter = function(keyFilter) { 
        self.filterKey(keyFilter); 
    };
    
    (function() {
        // Products
        self.wrappedProducts.push({"prod":"1"});
        self.wrappedProducts.push({"prod":"2"});
        // Offers
        self.availableOffers.push({"name": "offer1", "key": "1", "prod": 1});
        self.availableOffers.push({"name": "offer2", "key": "2", "prod": 1});
        self.availableOffers.push({"name": "offer3", "key": "2", "prod": 2});
    })();
}
var viewModel = new myViewModel();
ko.applyBindings(viewModel);

ul, h4 {margin-top: 0px; margin-bottom:0px;}
label {font-weight:bold;}

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<h4>All products</h4>
<ul data-bind="foreach: wrappedProducts">
    <li data-bind="text: ko.toJSON($data)"></li>
</ul>
<h4>Available offers</h4>
<ul data-bind="foreach: availableOffers">
    <li data-bind="text: ko.toJSON($data)"></li>
</ul>
<div>
    <button data-bind="click: function() {filter(1);}">key1</button>
    <button data-bind="click: function() {filter(2);}">key2</button>
    filterKey = <span data-bind="text: filterKey"></span>
</div>
<hr>
    <label for="prod1">Product 1</label>
<ul data-bind="foreach: filteredItems">
    <li data-bind="text: ko.toJSON($data)"></li>
</ul>
    <label for="prod2">Product 2</label>
<ul data-bind="foreach: filteredItems">
    <li data-bind="text: ko.toJSON($data)"></li>
</ul>
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:2)

Knockout会自动将您的绑定表达式包装在computed中,因此您实际上只需将filteredItems作为常规函数并使用要显示为参数的产品调用它:

filteredItems = function filteredItems(product) {
    return ko.utils.arrayFilter(self.availableOffers(), function (offer) {
        return offer.key == self.filterKey() && offer.prod == product;
    });
};

<label for="prod1">Product 1</label>
<ul data-bind="foreach: filteredItems(1)">
  <li data-bind="text: ko.toJSON($data)"></li>
</ul>

<label for="prod2">Product 2</label>
<ul data-bind="foreach: filteredItems(2)">
  <li data-bind="text: ko.toJSON($data)"></li>
</ul>

并在availableOffers更改时自动更新。

&#13;
&#13;
function myViewModel() {
    var self = this;
    self.wrappedProducts = ko.observableArray();
    self.availableOffers = ko.observableArray();
    self.filterKey = ko.observable(1);
    filteredItems = function filteredItems(product) {
        return ko.utils.arrayFilter(self.availableOffers(), function (offer) {
            return offer.key == self.filterKey() && offer.prod == product;
        });
    };
    
    self.filter = function(keyFilter) { 
        self.filterKey(keyFilter); 
    };
    
    (function() {
        // Products
        self.wrappedProducts.push({"prod":"1"});
        self.wrappedProducts.push({"prod":"2"});
        // Offers
        self.availableOffers.push({"name": "offer1", "key": "1", "prod": 1});
        self.availableOffers.push({"name": "offer2", "key": "2", "prod": 1});
        self.availableOffers.push({"name": "offer3", "key": "2", "prod": 2});
    })();
}
var viewModel = new myViewModel();
ko.applyBindings(viewModel);
&#13;
ul, h4 {margin-top: 0px; margin-bottom:0px;}
label {font-weight:bold;}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<h4>All products</h4>
<ul data-bind="foreach: wrappedProducts">
    <li data-bind="text: ko.toJSON($data)"></li>
</ul>
<h4>Available offers</h4>
<ul data-bind="foreach: availableOffers">
    <li data-bind="text: ko.toJSON($data)"></li>
</ul>
<div>
    <button data-bind="click: function() {filter(1);}">key1</button>
    <button data-bind="click: function() {filter(2);}">key2</button>
    filterKey = <span data-bind="text: filterKey"></span>
</div>
<hr>
    <label for="prod1">Product 1</label>
<ul data-bind="foreach: filteredItems(1)">
    <li data-bind="text: ko.toJSON($data)"></li>
</ul>
    <label for="prod2">Product 2</label>
<ul data-bind="foreach: filteredItems(2)">
    <li data-bind="text: ko.toJSON($data)"></li>
</ul>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

嗯,你只是显示相同计算结果。那么,这就是为什么在Prod 1和Prod 2下你获得相同的结果。如果您想按产品和密钥进行过滤,那么您需要两个可以为您过滤的计算函数。

您在arrayFilter中缺少的代码是:

var isCorrectKey = offer.key == self.filterKey();
var isCorrectProduct = offer.prod == 2;
return isCorrectKey && isCorrectProduct;

您必须检查产品和密钥。

&#13;
&#13;
function myViewModel() {
    var self = this;
    self.wrappedProducts = ko.observableArray();
    self.availableOffers = ko.observableArray();
    self.filterKey = ko.observable(1);
    filteredItemsKey1 = ko.computed(function () {
        return ko.utils.arrayFilter(self.availableOffers(), function (offer) {
            var isCorrectKey = offer.key == self.filterKey();
            var isCorrectProduct = offer.prod == 1;
            return isCorrectKey && isCorrectProduct;
        });
    });

    filteredItemsKey2 = ko.computed(function () {
        return ko.utils.arrayFilter(self.availableOffers(), function (offer) {
            var isCorrectKey = offer.key == self.filterKey();
            var isCorrectProduct = offer.prod == 2;
            return isCorrectKey && isCorrectProduct;
        });
    });
    self.filter = function(keyFilter) { 
        self.filterKey(keyFilter); 
    };
    
    (function() {
        // Products
        self.wrappedProducts.push({"prod":"1"});
        self.wrappedProducts.push({"prod":"2"});
        // Offers
        self.availableOffers.push({"name": "offer1", "key": "1", "prod": 1});
        self.availableOffers.push({"name": "offer2", "key": "2", "prod": 1});
        self.availableOffers.push({"name": "offer3", "key": "2", "prod": 2});
    })();
}
var viewModel = new myViewModel();
ko.applyBindings(viewModel);
&#13;
ul, h4 {margin-top: 0px; margin-bottom:0px;}
label {font-weight:bold;}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<h4>All products</h4>
<ul data-bind="foreach: wrappedProducts">
    <li data-bind="text: ko.toJSON($data)"></li>
</ul>
<h4>Available offers</h4>
<ul data-bind="foreach: availableOffers">
    <li data-bind="text: ko.toJSON($data)"></li>
</ul>
<div>
    <button data-bind="click: function() {filter(1);}">key1</button>
    <button data-bind="click: function() {filter(2);}">key2</button>
    filterKey = <span data-bind="text: filterKey"></span>
</div>
<hr>
    <label for="prod1">Product 1</label>
<ul data-bind="foreach: filteredItemsKey1">
    <li data-bind="text: ko.toJSON($data)"></li>
</ul>
    <label for="prod2">Product 2</label>
<ul data-bind="foreach: filteredItemsKey2">
    <li data-bind="text: ko.toJSON($data)"></li>
</ul>
&#13;
&#13;
&#13;