Search code examples
ractivejs

Ractive:execute one model's methods from another model


ref: this jsfiddle

(I don't know if this is a Ractive question or a plain-old-javascript question)

I have a Ractive model, "item":

window.item = new Ractive({
  el: "#container",
  template: "<p>words</p>",
  oninit: function() { window.little_ractive.set({ 'thing_to_do': this.do_this, 'item': this }); },
  do_this: function() { this.say("yeah baby"); },
  say: function(what) { console.log(what); }
});

Notice that the model initializes two attributes in another Ractive model, which looks like this:

window.little_ractive = new Ractive({
  finish: function() { this.get('thing_to_do').apply(this.get('item')); }
});

We can observe that little_ractive is properly initialized with attributes pointing to the item model and its "do_this" method.

If we now execute:

little_ractive.finish()

The context ('this') is incorrectly established in the "do_this" method, and it returns an error "this.say() is not a function"

How can the methods of one Ractive model be executed from another?

update: The jsfiddle uses Ractive version 1.0.0 build9. Ractive version 0.7.3 does not exhibit this problem, it works as one would expect.

update: The unexpected behaviour first appeared in version 0.8.0


Solution

  • Any functions that are stored at the root of a ractive instance's data are automatically bound to the instance e.g. ractive.set('foo', function () { console.log('this will always be ractive'); }). This is so that calling root functions execute as expected in templates.

    If you move functions that don't need to be bound one level deep e.g. ractive.set('fns.foo', function () { console.log('this is not bound'); }), then you can pass them around and call/apply them as needed. fiddle