filur
filur

Reputation: 1556

Referencing observable from inline computed method

Am I missing anything, or is it simply not possible to declare a computed "inline" property like id_and_name below in my first example?

function viewmodel(){

    var self = this;

    // adding 'inline' won't work (exception that the functions doesn't exist):
    self.person = ko.observable({
        id: ko.observable(),
        name: ko.observable(),
        id_and_name: ko.computed(function(){ return this.id() + this.name(); }, self.person)
    });

    // this works:
    self.person.id_and_name = ko.computed(function(){ 
        return this.id() + this.name(); 
    }, self.person);
}

Upvotes: 0

Views: 193

Answers (1)

Jeroen
Jeroen

Reputation: 63739

Well, self.person is undefined until after the ko.observable call has returned. The computed is bootstrapped before that, so it is bootstrapped at a moment when self.person is still undefined. You can check it out in the computed source code file, pretty easy to read actually.

Here's one way to look at that:

function viewmodel() {
  var self = this;

  self.person = "temp";

  self.person = ko.observable({
    id: ko.observable(),
    name: ko.observable(),
    id_and_name: ko.computed(function() {
      console.log(this);
      return this.id() + this.name();
    }, self.person)
  });
}

It'll log "temp" upon initializing, because that's what self.person is at that time. You cannot change the this target for the computed read function after it was created.

So nope, what you want can't be done. You need your second solution or a proper view model constructor function*.


* Your top level viewmodel is already such a constructor function. You could create an inner constructor funciton person with id and name properties, and new that up, give it a id_and_name computed that will automatically have the correct this bound.

Upvotes: 1

Related Questions