更新父级时刷新选定的可观察对象 [英] Refreshing a selected observable when parent is updated

查看:71
本文介绍了更新父级时刷新选定的可观察对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我之前曾问过这个问题,但是并没有得到太多回应.很明显,我不清楚要达到的目标,所以我会再试一次.

我正在开发一个(间隔)调用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆