更新父级时刷新选定的可观察对象 [英] Refreshing a selected observable when parent is updated
问题描述
我之前曾问过这个问题,但是并没有得到太多回应.很明显,我不清楚要达到的目标,所以我会再试一次.
我正在开发一个(间隔)调用Web方法的应用程序,该方法将读取数据库并构建一个JSON字符串以返回,该字符串用于构造我的视图模型.当我的视图模型发生变化时,我需要使用新数据对所有选定的可观察对象进行变异.
I'm working on an app that will (at an interval) call a web method, which will read a database and build up a JSON string to return which is used to construct my view model. When my view model changes I need to mutate all selected observables with the new data.
以此为基础模型示例.
var model = {
people: [
{ forename: "Test", surname: "Person", numbers: [1,2,3] },
{ forename: "Another", surname: "Test", numbers: [4,5,6] }
]
};
非常简单,当在模态上单击一行时,将弹出一个人的表,其中显示了所选人所拥有的numbers
的列表.打开此模式后,可能会在后台更新数据,因此,如果选择了[Test Person](并且弹出了模式),并且有人在某个地方将[7,8,9]
添加到其numbers
中,那么我需要刷新该模式显示这些添加内容.
Simple enough, a table of people that when a row is clicked on a modal will pop up showing a list of numbers
the selected person has. While this modal is open, the data could be being updated behind the scenes so if [Test Person] is selected (and the modal pops up) and someone, somewhere adds [7,8,9]
to their numbers
then I need the modal to refresh showing these additions.
这是一个基本的视图模型(为简便起见,使用ko.mapping
):
Here's a basic view model (using ko.mapping
for brevity):
var viewModel = {
people: ko.mapping.fromJS(model.people),
selectedPerson: ko.observable(null),
refresh: function () {
ko.utils.arrayForEach(model.people, function (person) {
var last = person.numbers[person.numbers.length - 1];
var newNumber = last + 1;
person.numbers.push(newNumber);
});
ko.mapping.fromJS(model.people, this.people);
console.log(ko.toJSON(this));
}
};
当单击一行时,此人存储在selectedPerson
中,这使我的模态在UI中可见(我正在使用Zurb Foundation):
When a row is clicked on, the person is stored in selectedPerson
which makes my modal become visible in the UI (I'm using Zurb Foundation):
<div id="modal" class="reveal-modal" data-bind="if: selectedPerson">
此模式显示numbers
的表以及名为Update Observable的按钮-它将调用一个函数来模拟对基础模型的更改(在这种情况下,我将numbers
中的最后一项取为1)并继续进行下去).完成此操作后,我然后重新创建我的视图模型(为简便起见,使用ko.mapping
),并期望UI上的所有内容都可以更新以反映更改-除了模态之外,一切都很好.
This modal shows a table of numbers
with a button named Update Observable - this calls a function to emulate the changes to the underlying model (in this case I'm taking the last item in numbers
incrementing it by 1 and pushing it on). When this is done I then re-create my view model (using ko.mapping
for brevity) and expect everything on the UI to be updated to reflect the change - all fine apart from the modal.
重新映射后查看我的视图模型的JSON,我可以看到视图模型已正确更新,但selectedPerson
尚未更新.我以为selectedPerson
是参考,而不是副本,但是我显然以为是错误的,我们最终得出结论.
Looking at the JSON of my view model after re-mapping I can see that the view model has been updated correctly, but the selectedPerson
hasn't. I assumed selectedPerson
was a reference, not a copy, but I obviously assumed wrong and we end up with this.
{
"people": [
{
"forename": "Test",
"surname": "Person",
"numbers": [1,2,3,4,5,6,7,8]
},
{
"forename": "Another",
"surname": "Test",
"numbers": [4,5,6,7,8,9,10,11]
}
],
"selectedPerson": {
"forename": "Test",
"surname": "Person",
"numbers": [1,2,3]
}
}
所以我想我的问题是:当基础模型发生变化时,如何更新selectedPerson
(或者实际上可能有其他选择的观察值)?
So I suppose my question is: how do I update selectedPerson
(or in fact any other selected observable there may be) when the underlying model changes?
推荐答案
您的问题是ko.mapping.fromJS(model.people, this.people)
清空并重新创建您的people
集合.但是您的selectedPerson
仍然引用了旧的person
对象之一.
Your problem is that the ko.mapping.fromJS(model.people, this.people)
empties and recreates your people
collection. But your selectedPerson
still references one of the old person
object.
您需要告诉映射插件您想如何识别商品,以便对其进行更新:
You need to tell the mapping plugin how you want to identify your items so it will update them:
ko.mapping.fromJS(model.people,
{ key: function(item) { return item.forename; } },
this.people);
演示 JSFiddle .
或者作为替代解决方案,您可以在映射后将selectedPerson
重置为新创建的person
对象之一:
Or as an alternative solution you can reset your selectedPerson
to one of the the newly created person
object after the mapping:
this.selectedPerson(ko.utils.arrayFirst(this.people(), function(item){
return item.forename() == this.selectedPerson().forename();
}, this));
演示 JSFiddle .
这篇关于更新父级时刷新选定的可观察对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!