访问外部observableArray以更改其中一个属性。
我的申请表中有两个列表。其中一个列表包含我添加到其中的商店商品 - 非常类似于购物车;另一个清单是可购买的产品。每个产品都有一个“添加按钮”,当我点击它时,就像魔术一样,它出现在“购物车”上。
要从购物车中删除此产品,我们必须单击添加我们产品的同一按钮,因为其状态更改为“删除”。或者,我们可以点击列表中添加的项目旁边 - 那里有一个“删除按钮”。
直到这里,一切正常。问题是:当我通过点击购物车的“x”删除产品时,产品的按钮不会恢复正常。换句话说,该按钮不会返回“添加按钮”。
要查看说明性示例just click here to go to jsFiddle。
我需要从self.products = ko.observableArray(products);
访问ProductViewModel
上的SummaryViewModel
。
如果jsFiddle出现问题,代码如下。
HTML:
<ul class="summary">
<!-- ko foreach: Summary.items -->
<p data-bind="text: name"></p>
<button class="btn btn-danger btn-mini remove-item">
<i class="icon-remove">×</i>
</button>
<!-- /ko -->
</ul>
<h1>What would you to buy?</h1>
<ul class="products">
<!-- ko foreach: Product.products -->
<li>
<h3 data-bind="text: name"></h3>
<p data-bind="text: desc"></p>
<!-- ko if:isAdded -->
<button data-bind="if: isAdded" class="btn btn-small btn-success action remove">
<i data-bind="click: $root.Summary.remove" class="icon-ok">Remove</i>
</button>
<!-- /ko -->
<!-- ko ifnot:isAdded -->
<form data-bind="submit: function() { $root.Summary.add($data); }">
<button data-bind="ifnot: isAdded" class="btn btn-small action add">
<i class="icon-plus">Add</i>
</button>
</form>
<!-- /ko -->
</li>
<!-- /ko -->
</ul>
JavaScript的:
function Product(id, name, desc) {
var self = this;
self.id = ko.observable(id);
self.name = ko.observable(name);
self.desc = ko.observable(desc);
self.isAdded = ko.observable(false);
}
function Item(id, name) {
var self = this;
self.id = ko.observable(id);
self.name = ko.observable(name);
}
function SummaryViewModel() {
var self = this;
self.items = ko.observableArray([]);
self.add = function (item) {
self.items.push(new Item(item.id(), item.name()));
console.log(item);
item.isAdded(true);
};
self.remove = function (item) {
var i = self.items().filter(function(elem){
return elem.id() === item.id();
})[0];
self.items.remove(i);
item.isAdded(false);
};
};
function ProductViewModel(products) {
var self = this;
self.products = ko.observableArray(products);
};
var products = [
new Product(1, "GTA V", "by Rockstar"),
new Product(2, "Watch_Dogs", "by Ubisoft")
];
ViewModel = {
Summary: new SummaryViewModel(),
Product: new ProductViewModel(products)
}
ko.applyBindings(ViewModel);
答案 0 :(得分:1)
发生这种情况的原因是,当您将项目推送到摘要列表时,它不再具有isAdded或desc属性。您需要将这些添加到摘要模型中或直接传递项目,而不是创建新对象。
JavaScript抛出错误('没有属性'isAdded')是我所知道的。在运行控制台时打开控制台以查看错误。
添加console.log(item);向我展示了它拥有的属性。
self.remove = function (item) {
var i = self.items().filter(function(elem){
return elem.id() === item.id();
})[0];
self.items.remove(i);
console.log(item);
item.isAdded(false);
};
给我一点时间,我会更新你的小提琴。
这是一个有效的例子。我删除了一些冗余(例如,当您已经拥有它时,通过并过滤产品)
答案 1 :(得分:1)
最好不要在两个不同的地方跟踪有关对象的相同信息。这将始终导致同步问题。
在您的情况下,您可以跟踪对象是否“已添加” ...
isAdded
可观察对象)和items
可观察对象)失去两个地方是很有用的。
例如,您可以删除手动列表,并在产品模型中跟踪对象状态。
然后你可以使用一个计算的observable来返回所选产品的过滤视图(ko.utils.arrayFilter
),Knockout会完成所有其他产品。
function Product(id, name, desc) {
var self = this;
self.id = ko.observable(id);
self.name = ko.observable(name);
self.desc = ko.observable(desc);
self.isAdded = ko.observable(false);
self.addRemoveText = ko.computed(function () {
return self.isAdded() ? "Remove" : "Add";
});
self.addRemove = function () {
self.isAdded(!self.isAdded());
};
}
function SummaryViewModel(parent) {
var self = this;
self.items = ko.computed(function () {
var products = ko.utils.unwrapObservable(parent.products);
return ko.utils.arrayFilter(products, function (product) {
return product.isAdded();
});
});
}
function ProductViewModel(parent) {
var self = this;
self.items = ko.observableArray(parent.products);
}
function ViewModel(products) {
var self = this;
self.products = ko.utils.arrayMap(products, function (init) {
return new Product(init.id, init.name, init.desc);
});
self.Summary = new SummaryViewModel(self);
self.Product = new ProductViewModel(self);
}
在此处观看:http://jsfiddle.net/Tomalak/Jr3Tk/4/
另请注意,基本HTML变得更加简单。
<ul class="summary" data-bind="with: Summary">
<!-- ko foreach: items -->
<li>
<p data-bind="text: name"></p>
<button class="btn btn-danger btn-mini remove-item" data-bind="click: addRemove">
<i class="icon-remove">×</i>
</button>
</li>
<!-- /ko -->
</ul>
<h1>What would you to buy?</h1>
<ul class="products" data-bind="with: Product">
<!-- ko foreach: items -->
<li>
<h3 data-bind="text: name"></h3>
<p data-bind="text: desc"></p>
<button class="btn btn-small btn-success action remove">
<i data-bind="click: addRemove, text: addRemoveText" class="icon-ok">Remove</i>
</button>
</li>
<!-- /ko -->
</ul>
答案 2 :(得分:0)
ProductViewModel.products.subscribe(function(products){
SummaryViewModel.products(products);
});
但首先您需要在self.products = ko.observableArray([]);
SummaryViewModel
我理解正确吗?