0

basically looking mapping a json from ajax call. my 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);
        }
    }    
};

I get an error : ReferenceError : fullAddress is not defined my fiddle: http://jsfiddle.net/2coj72yn/1/ Thanks for hope.

2 Answers2

0

Use the $data prefix

<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>...

Sample: http://jsfiddle.net/baryon/NsuL7/1/

Source: knockout viewmodel property undefined

Community
  • 1
  • 1
BrennQuin
  • 656
  • 10
  • 19
0

There are various problems with your code, but it won't throw an error because the mapping plugin is used improperly.

The problem of scope

First, fullAddress is a property of Address instances, so you should prefix it with address. Second, the with binding tells Knockout to look for editingPerson.savePerson which doesn't exist. So you have to change the binding to the root scope, like so: 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>

It is also advised to use objects as constructor parameter, allowing for easier use in combination with the mapping plugin and should you wish to leave out one property.

The mapping plugin

The mapping plugin documentation clearly states that:

All properties of an object are converted into an observable.

This means that you cannot include computed observables and expect them to just work. Indeed, the documentation has a part about augmenting JS objects with computed observables here. I might be wrong, but from my tests and the docs, it doesn't seem so that the create functions for mapping can be used for nested objects. Following this documentation, you don't need to create all observable properties explicitly, as a single call to ko.mapping.fromJS can instantiate them. Your new Person constructor would look like this:

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();
    });  
}

Another minor 'nit-pick': you can only use the mapping plugin's create functions on named object properties, so in your original fiddle, the plugin will never find the persons array because it is the data root.

Check out this fiddle for the complete solution.

webketje
  • 10,376
  • 3
  • 25
  • 54