Closed foxyblocks closed 11 years ago
You could certainly extend your base view from Epoxy.View
to add Epoxy into your inheritance chain, although I wouldn't suggest it. That would make every view in your app binding, which probably isn't appropriate. Sounds like you'd be best off just creating a new BindingBaseView
, which would be a new extension of Epoxy.View
that mixes in your base view's prototype along with additional (optional) implementation, as in:
App.BindingBaseView = Backbone.Epoxy.View.extend( _.extend({}, App.BaseView.prototype, {
// additional optional implementation here...
}) );
That should work unless your view overrides the native Backbone.View
constructor, at which time you'll need to define a new constructor implementation that calls up to the Epoxy view constructor.
Is it not possible to do it the opposite direction?
App.BindingBaseView = App.BaseView.extend(Backbone.Epoxy.View.prototype,{ // additional optional implementation here... });
Thus treating epoxy as the plugin of the relationship?
It just seems that there are so many backbone.x libraries that want you to inherit from their View or Model prototypes.
Maybe I'm wrong and this isn't a real issue but I tend to want my libraries to be as pluggable as possible.
I definitely hear you; unfortunately the Backbone inheritance model is a bit tricky in this regard. I just amended my previous response, where I'd actually misquoted the usage of Backbone's class extension. The most deceptive point here is that the Backbone.[Class].extend
method is not just another implementation of Underscore's extend
method. While Underscore extension is just simple property mixins between objects, the Backbone class extension is actually setting up constructor chains used to control how objects are built. If a library component defines a custom constructor operation (many do, including Epoxy), then its class must be extended to preserve the constructor's role. This also preserves class identity, as determined using instanceof
.
For the kind of extension you're referring it, that really only works for mixin libraries that simply offer a suite of utilities to graft onto your object prototypes... for example: Backbone.Events
is a mixin library, versus a constructed component such a Backbone.View
which must be extended.
We use Marionette which has its own view hierarchy, so we can't extend Epoxy.View directly. Instead, we're just mixing in Epoxy by adding the following to the initialize method (or the constructor) of our view base classes:
_.extend(this, _.pick(Epoxy.View.prototype, "applyBindings", "removeBindings", "bindings"), {
_bind: []
});
this.listenTo(this, "render", this.applyBindings);
this.listenTo(this, "before:close", this.removeBindings);
Obviously this isn't future-proofed as it won't automatically pick up new Epoxy.View methods, but it does work.
Formal class mixins have now been added into the edge branch. The next release of Epoxy provides calls to Backbone.Epoxy.View.mixin()
and Backbone.Epoxy.Model.mixin()
; these methods will generate an Epoxy class abstract that may be mixed into your class prototypes... from there you'll just need to manually perform some simple setup calls while initializing your class instances.
Can you elaborate on "you'll just need to manually perform some simple setup calls while initializing your class instances"? I'm also trying to mixin the Epoxy.View to my BaseBindingView which extends from Marionette. I got my ideas from here: http://www.salsify.com/blog/data-binding-in-backbone-with-epoxy and from this thread.
BaseBindingItemView = Marionette.ItemView.extend({
constructor: function(){
Marionette.ItemView.apply(this, arguments);
this.epoxify();
},
epoxify: function () {
Epoxy.View.mixin(this);
this.listenTo(this, "ui:bind", this.applyBindings);
this.listenTo(this, "before:close", this.removeBindings);
},
bindUIElements: function(){
this.trigger("ui:bind");
Marionette.View.prototype.bindUIElements.apply(this, arguments);
}
});
I'm struggling with my child views which extend BaseBindingItemView.
var ChildView = BaseBindingItemView.extend({
template: //a handlebars template function
bindings: {
".selector": "text:attribute"
}
});
The problem is that bindings in ChildView is added to the prototype, and then Epoxy.View.mixin(this) adds the default bindings: "data-bind" to the instance. Then applyBindings has nothing to do.
The only way I can think to workaround this is to add the bindings in the template, which is something I'd rather not have to.
Any suggestions?
I'd recommend just re-implementing mixin()
on Epoxy. The function is pretty simple.
Still, seems like a bug.
Nice to see you're following our post!
Is there a way to use Epoxy.View without extending it directly? i.e:
Many people when using backbone have their own base view class:
How can multiple inheritance be achieved?