2

I have a very simple example that is not working.

jsfiddle: http://jsfiddle.net/ThomasDeutsch/8hzhp/3/

// My Model
function Customer(id, name, lastname) {
    this.Id = ko.observable(id);
    this.Name = ko.observable(name);
    this.LastName = ko.observable(lastname);
}

// My ViewModel
ViewModel = (function () {
    var getName = ko.computed(function (x) {
        return x.Name();
    });

    return {
        getName: getName(new Customer(1, "Thomas", "D"))
    };
})();

ko.applyBindings(ViewModel);​

problem: parameter (x) is undefined

goal: return the Name-Property of the called Object - i want to use the x as a property so that i can call this function with any Object with a observable Name property

Code explanation: This is done using the revealing-module-pattern with knockout.js. The Name-property is a ko.observable() - so the () is needed.

question: Why is x undefined?

Thomas Deutsch
  • 2,344
  • 2
  • 27
  • 36

2 Answers2

3

Let me ask you. Where do you think x is defined?

You are calling getName and passing a Customer, but getName doesn't expect a parameter.

If you rewrite your function like this it will work:

var getName = function(x) { return ko.computed( function() {
    return x.Name();
})};
John Earles
  • 7,194
  • 2
  • 37
  • 35
  • Now i get it! Tank you. I thought hat i could use the ko.computed function as a sort of reference. Ok since the Name property is already a ko.observable function i do not need the ko.computed -> result: http://jsfiddle.net/ThomasDeutsch/8hzhp/6/ – Thomas Deutsch Jun 03 '12 at 20:01
  • As you are now returning an observable you can also remove the () and just do: `return x.Name;`. The text binding knows how to work with the observable. – John Earles Jun 03 '12 at 20:10
1

You're trying to change the value of the observable "getName", but since it's a computed one, that's undefined behavior until you specify how this should be handled.

I think the best solution would be to introduce another observable that stores the customer.

var ViewModel = (function() {
    // Observable for the customer
    var customer = ko.observable(new Customer(1, "Thomas", "D"));

    // The computed observable, using the other one
    var getName = ko.computed(function() {
        return customer().Name();
    });

    // If you only need to access the name, its sufficient
    // to export only that observable. However, this is still
    // read-only.
    return {
        getName: getName
    };
})();

If you want to make it writable, you can define a setter for the computed observable:

var getName = ko.computed({
    read: function() {
        return customer().Name();
    },
    write: function(n) {
        customer().Name(n);
    }
});

(not an example that makes the most sense, but that is because you don't really need a computed observable here)

Niko
  • 26,516
  • 9
  • 93
  • 110