Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Knockout subscribe scope

Is there any possibility to change the scope of the subscribe in Knockout?

I have something like this:

element =
    {
        type: ko.observable()
        name: ko.observable()
        content: ko.observable()
    }

element.type.subscribe(this._typeChanged.bind(element))

Basically I want to have an access to the object which property I am subscribed to. Binding like in my code does nto work since it binds to the whole VeiwModel and not the object.

like image 295
RobertPorter Avatar asked Mar 15 '23 01:03

RobertPorter


2 Answers

Maybe the knockout handle that when you subscribe an observable you can pass 2 parameters the first is the callback and the second is the scope/context, try something like this:

element.type.subscribe(this._typeChanged, element)

The subscribe function accepts three parameters: callback is the function that is called whenever the notification happens, target (optional) defines the value of this in the callback function, and event (optional; default is "change") is the name of the event to receive notification for.

Ref. http://knockoutjs.com/documentation/observables.html

like image 93
Joel R Michaliszen Avatar answered Mar 19 '23 06:03

Joel R Michaliszen


The problem is the way in which you're creating your view model. The view model shuld be self-contained, including the functions that operate on it. It should be something like this:

var ViewModel = function() {
    var self = this;
    self.type = ko.observable();
    self.name = ko.observable();
    self.content = ko.observable();
    self.type.subscribe(function(newVal) {
        // here you have access to all the viewmodel properties through self
    });
    return self;
};

This is a constructor using the var self=this; pattern.To use the view model you need to instantiate it, i.e. var vm = new ViewModel(). (You can omit the new).

Of course, you can also define a function, and bind it to self, or receive a callback in the constructor, and bind it to self. In that case, the function implementation will have the view model accesible via this, and not self, which will be undefined inside the function body.

var doSomethignWithVm = function(newVal) {
    // acces viewmodel via this
    // you can also use newVal
};

You modify the constructor to receive this as a callback:

var ViewModel = function(doSomethingCallback) {
    self.type.subscribe(callback.bind(self));
};

This pattern doesn't make much sense because your callback is supposed to have knowledge of your view model. In that case it makes more sense to include the subscription functionality directly inside the model.

EDIT Note: as I've mentioned in a comment to Joel Ramos Michaliszen's answer, both of this codes are equivalent:

self.type.subscribe(callback.bind(self));
self.type.subscribe(callback.bind, self);

You can check that by seeing the source code of subscribable in knockout's gitbhub, in the file knockout/src/subscribales/subscribable.js. If you look for subscribe implementation you'll see this:

subscribe: function (callback, callbackTarget, event) {
    // ...
    boundCallback = callbackTarget ? callback.bind(callbackTarget) : callback;

I.e. if you provide a second argument, it's used tob bind the function passed in the firt argument to it.

like image 35
JotaBe Avatar answered Mar 19 '23 06:03

JotaBe