Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to proxy methods on the prototype using ObjectProxy in ember.js?

Tags:

ember.js

I've got a simple ObjectProxy that I'd like to make calling methods on easy(er). For example, the object I plan to "proxy" has a method named foo and bar - they will not be available directly causing me to do something like this.

this.get("model").get("content").foo();
this.get("model").get("content").bar();

Instead I'd much prefer if foo and bar acted like they were on the object

this.get("model").foo();
this.get("model").bar();

I can make this happen (long hand) by hard coding the foo and bar methods on the ObjectProxy itself - then pulling content and invoking the method manually w/ apply like so

  return Ember.ObjectProxy.extend({
        content: function() {
            var filter_value = this.get("filter_value");
            return this.get("source").filterBy("id", filter_value).objectAt(0);
        }.property("source.[]"),
        foo: function() {
            var content = Ember.get(this, 'content');
            return content["foo"].apply(content, arguments);
        },
        bar: function() {
            var content = Ember.get(this, 'content');
            return content["bar"].apply(content, arguments);
        }
    }).create({
        filter_value: id,
        source: store.find(type)
    });

If instead I wanted to proxy each "method" like this - how can I set the prototype in a way that won't hurt the tree that ember has built up already?

like image 301
Toran Billups Avatar asked Mar 29 '15 21:03

Toran Billups


1 Answers

I'm not necessarily recommending this, but it's an idea, if you don't want to always define the functions. To be honest, this wouldn't be a terrible idea of something to add to ember, I hate having to go two levels deeps to hit the functions.

Code Change

Ember.ObjectProxy.reopen({
  addFunc: function (content, method) {
    this[method] = function () {
      if (!content[method]) return;
      return content[method].apply(content, arguments);
    };
  },
  setupMethods: Ember.observer('content', function () {
    var content = this.get('content');

    if (!content) return;

    for (var item in content) {
      if (typeof content[item] == "function") {
        if (!this[item]) { // watch out for clashing names
          this.addFunc(content, item);
        }
      }
    }
  })
});

I think tracking the added methods, and possibly cleaning up after content changes wouldn't be a terrible thing, but I doubt a single object proxy often holds more than one underlying object.

Examples

var o = Ember.ObjectProxy.create();

console.log(o.foo);

o.set('content', {
  foo: function(){
    console.log('hello');
  }
});

console.log(o.foo);

o.foo();

o.set('content',{
  bar: function(){
    console.log('bar');
  }
});

o.bar();

Example: http://emberjs.jsbin.com/juwomezape/1/edit

The caveat being that, until the content is defined, no methods exist, but often we have resolved objects before we even start messing with them anyway.

like image 104
Kingpin2k Avatar answered Sep 30 '22 19:09

Kingpin2k