I have a generic subclass of Backbone.View
which has a close
event listener.
var GenericView = Backbone.View.extend({
events
Here's a solution that's worked well for me. You can use the events object in both parent and subclass without extending in it each subclass. Just extend it once in the parent class:
APP.Views.GenericWizard = Backbone.View.extend({
events: {
'click .btn-prev' : function(){}
},
initialize: function() {
_(this.events).extend(APP.Views.GenericWizard.prototype.events);
}
});
APP.Views.RegisterWizard = APP.Views.GenericWizard.extend({
events: {
'blur #username' : function(){}
},
});
var registerWizard = new APP.Views.RegisterWizard();
console.log(registerWizard.events);
// Object {blur #username: function, click .btn-prev: function}
@Nupul is exactly right: you're not subclassing your GenericView
.
In fact, subclassing isn't really the right word here, since JavaScript doesn't do classical inheritance.
So let's first try and understand what's happening here:
var GenericView = Backbone.View.extend( propertiesObj, classPropertiesObj )
Backbone.View
is a constructor function, that when called with the new
keyword, creates a new object for you.
Since this is JS, all function are really function objects, so Backbone.View.extend
is just a function hanging off Backbone.View
that does a few things:
GenericView
) to instantiate objects of your inheriting classSo the correct way to set up the protoype chain you want is:
var ImplementedView = GenericView.extend({
// implementation goes here
});
and NOT:
var ImplementedView = new GenericView({//stuff});
because this just creates a new instance of a GenericView.
Now, you still have a problem, because when you do something like:
var impl_view = new ImplementedView;
impl_view.events; // This isn't merged with the events you created
// for the GenericView
At this point there are different ways to get the result you want, here's one that uses delegateEvents
kind of like how you did. Using it isn't bad, incidentally.
var GenericView = Backbone.View.extend({
genericEvents: { 'click .close': 'close' },
close: function() { console.log('closing view...'); }
});
var ImplView = GenericView.extend({
events: { 'click .submit': 'submit' },
initialize: function(options) {
// done like this so that genericEvents don't overwrite any events
// we've defined here (in case they share the same key)
this.events = _.extend({}, this.genericEvents, this.events);
this.delegateEvents()
}
});
I like Mr. Shaver's solution, but for something less intrusive:
var ChildView = ParentView.extend({
events : _.extend({
"change input": "handleInputChange"
}, ParentView.prototype.events)
});
Edit: Yes, you have to do this in each child class, but it's useful when only a few children are needed, or when you don't control the parent "class".
Another option is to have a BaseView that overrides the implementation of Extend. Such as:
var BaseView = Backbone.View.extend({
//base view functionality if needed
});
BaseView.extend = function(child){
var view = Backbone.View.extend.apply(this, arguments);
view.prototype.events = _.extend({}, this.prototype.events, child.events);
return view;
};
This will automatically extend all of your events for anything that inherits from the BaseView.
You may find this useful: http://kalimotxocoding.blogspot.com/2011/03/playing-with-backbonejs-views.html
Seconds what I mentioned about _.extend(...)
and what you currently have...