knockoutjs 映射嵌套元素不具有约束力

knockoutjs mapping nested elements is not binding

基本上是从 ajax 调用映射 json。 我的 js

var mapping = {
    create: function(options) {
    return new Person(options.data.id,options.data.name,options.data.surname,options.data.address,options.data.amounts);
    },
    'address': {
        create: function(options) {
            return new Address(options.data.id,options.data.street,options.data.number);
        }
    },
    'Amounts': {
        create: function(options) {
            return new Amount(options.data.id,options.data.price,options.data.iva);
        }
    }    
};

我得到一个错误:ReferenceError:fullAddress is not defined 我的小提琴:http://jsfiddle.net/2coj72yn/1/ 感谢希望。

使用 $data 前缀

<div data-bind="with:$data.editingPerson">
    id: <input data-bind="value:$data.id"> <br>      
    name: <input data-bind="value:$data.name"> <br>
    surname: <input data-bind="value:$data.surname"> <br>
    Full Name: <input data-bind="value:$data.fullName"> <br>
    Address: <input data-bind="value:$data.fullAddress"> <br>
   <table>...

样本:http://jsfiddle.net/baryon/NsuL7/1/

来源:knockout viewmodel property undefined

你的代码存在各种问题,但不会因为映射插件使用不当而报错。

作用域问题

首先,fullAddress 是 属性 个 Address 实例,因此您应该在其前面加上 address. 其次,with 绑定告诉 Knockout查找不存在的 editingPerson.savePerson。所以你必须改变对根作用域的绑定,像这样:click: $root.savePerson.

<!-- current --> inputAddress: <input data-bind="value: fullAddress">
<!-- correct --> inputAddress: <input data-bind="value: address.fullAddress">

<!--current --> <button data-bind="click:savePerson" type="button">Save</button>
<!--correct --> <button data-bind="click:$root.savePerson" type="button">Save</button>

还建议使用对象作为构造函数参数,这样可以更轻松地与 mapping plugin 结合使用,如果您希望省略一个 属性.

映射插件

映射插件文档明确指出:

All properties of an object are converted into an observable.

这意味着您不能包含 computed observables 并期望它们正常工作。实际上,该文档有一部分是关于使用计算的可观察对象 here 来扩充 JS 对象。我可能是错的,但从我的测试和文档来看,映射的 create 函数似乎不能用于嵌套对象。按照本文档,您不需要显式创建所有可观察属性,因为对 ko.mapping.fromJS 的单个调用可以实例化它们。您的新 Person 构造函数将如下所示:

function Person(options){
    // because these arrays contain nested objects with computed observables,
    // they should have a special create function
    var self = this, mapping = {
        'amounts': { create: function(options) { return new Amount(options.data); }},
        'address': { create: function(options) { return new Address(options.data); }}
    };  
    // instantiates all properties, eg. surname, name, id
    ko.mapping.fromJS(options, mapping, this);
    self.fullName   = ko.computed(function() {
        return self.name()+" - "+self.surname();
    });  
}

另一个小问题'nit-pick':你只能在命名对象属性上使用映射插件的create函数,所以在你原来的fiddle中,插件永远找不到persons 数组,因为它是数据根。

查看 this fiddle 以获得完整的解决方案。