Knockout Mapping - 填充Observable Arrays保持Items的方法

时间:2012-08-06 13:20:42

标签: ajax knockout.js knockout-mapping-plugin ko.observablearray

我一直面临着一个基本上如下的问题:

  • 我有一个淘汰ViewModel,它包含带有可观察属性和方法的可观察项目数组。
  • 我需要从服务器提取数据。从服务器获取数据后,需要存在这些方法。所以我创建了一个新的ViewModel,然后从服务器来源更新它的值。 (这不起作用,结果阵列没有项目)
  • 如果我使用mapping使用var newObj = ko.mapping.fromJS(data)创建一个新对象,则生成的数组包含项,但其项目没有方法。它破坏了我的Bindings。

我的问题的小提示:http://jsfiddle.net/claykaboom/R823a/3/(它可以帮助您点击“从服务器加载数据”

最后一个问题是:在不使加载过程过于繁琐的情况下,在最终数组上放置项目的最佳方法是什么,例如迭代每个项目并填充项目的属性以保留先前声明的方法?

谢谢,

1 个答案:

答案 0 :(得分:2)

我稍微改变了你的代码。请检查此版本的JSFiddle

 var jsonFromServer = '{"ModuleId":1,"Metadatas":[{"Id":1,"MinValue":null,"MaxValue":null,"FieldName":"Teste","SelectedType":"String","SelectedOptionType":null,"IsRequired":true,"Options":[]}]}';

您的代码不起作用,因为您的jsonFromServer变量不包含我们在您的问题中描述的绑定所需的方法。 ( - > Metadatas)

因此,我们需要在映射过程中为元数据对象定义自定义创建函数,如下所示:

var mapping = {
    'Metadatas': {
        create: function(options) {
            var newMetaData = new MetadataViewModel(options.parent);

            newMetaData.Id(options.data.id);
            newMetaData.FieldName(options.data.FieldName);
            newMetaData.SelectedType(options.data.SelectedType);
            newMetaData.SelectedOptionType(options.data.SelectedOptionType);
            newMetaData.IsRequired(options.data.IsRequired);
            newMetaData.Options(options.data.Options);

            // You can get current viewModel instance via options.parent
            // console.log(options.parent);

            return newMetaData;
        }
    }
}

然后我将你的加载功能更改为:

self.LoadDataFromServer = function() {

    var jsonFromServer = '{"ModuleId":1,"Metadatas":[{"Id":1,"MinValue":null,"MaxValue":null,"FieldName":"Teste","SelectedType":"String","SelectedOptionType":null,"IsRequired":true,"Options":[]}]}';

    ko.mapping.fromJSON(jsonFromServer, mapping, self);
}

您不必声明新的viewModel并再次调用ko.applyBindings。将更新的映射分配给当前viewModel就足够了。有关更多信息,请查看this link。注意自定义对象构造部分。

  

最后一个问题是:在决赛中获得项目的最佳方式是什么   数组没有使加载过程过于繁琐,如   迭代每个项目并填充项目的属性以便   保留以前声明的方法?

据我所知,对象实现没有简单的方法可以做到这一点。你的对象并不简单。它们包含数据和功能。所以你需要为它们定义自定义创建功能。但是如果你能够像下面这样分开,那么你就不必自定义对象构造。

例如,将MetadataViewModel分隔为两个不同的对象:

 --> Metadata  : which contains only simple data
 --> MetadataViewModel : which contains Metadata observableArray and its Metadata manipulator functions

使用此结构,您可以调用ko.mapping.fromJSON(newMetaDataArray,{},MetadataViewModelInstance.MetadataArray),而无需在映射过程中定义自定义创建函数。