Reputation: 928
I use a clean backbone without wrappers or frameworks.
So I create a site to manage by some products. I have two dynamic pages for this:
add.php
edit.php
These pages are separate backbone applications.
In both pages, there is an element displays a product category. Usually it is a drop-down list.
Next, I will describe the approximate structure of my scripts. It is simple.
js
+- models
| +- Category.js
| ...
+- collections
| +- Categories.js
| ...
+- views
| +- CategoriesView.js
| ...
CategoryView.js contains:
App.Views.CategoriesViews = Backbone.View.extend({
template: _.template($('#tpl-categories').html()),
events: {
'change select': 'toggle'
},
initialize: function () {
_.bindAll(this, 'render');
this.collection.on('reset', this.render);
},
render: function () {
this.$el
.html(this.template({ collection: this.collection.toJSON() }));
return this;
},
toggle: function () {
// Some actions here
var catId = this.$el.children('select').val();
App.trigger('toggleCategories', catId);
}
});
Initialization of the view looks like this:
new App.Views.CategoriesViews({
el: $('#select-box-cats'),
collection: new App.Collections.Categories
});
Since this element is on both pages (add.php and edit.php) it works well for both of them.
We assume that the name of the template can be set the same on both pages:
<script type="text/template" id="tpl-categories">
Although I think it is not a good practice.
Well, finally my question.
What happens if one of these pages need to add an event handler to the view. For example:
initialize: function () {
_.bindAll(this, 'render', 'action');
this.collection.on('reset', this.render);
this.collection.on('request', this.action);
},
I added an event to request
collection. However, this event should not be present on another page.
What to do? To create a separate view file with the changes to the needs of the page? But it violates the principle of DRY and spawns a lot of client code!
Upvotes: 1
Views: 186
Reputation: 691
You can pass options to the view when you create it.
On your edit page:
new App.Views.CategoriesViews({
el: $('#select-box-cats'),
collection: new App.Collections.Categories,
bindRequest: true, // Trigger the request event.
toggleCategories: true // Toggle the categories in the toggle method.
});
On your add page:
new App.Views.CategoriesViews({
el: $('#select-box-cats'),
collection: new App.Collections.Categories,
bindRequest: false, // Do not trigger the request event.
toggleCategories: false // Do not toggle categories in the toggle method.
});
And in your view:
initialize: function() {
_.bindAll(this, 'render', 'action');
this.collection.on('reset', this.render);
// this.options is automatically populated with any parameters included
// upon creation.
if (this.options.bindRequest) {
this.collection.on('request', this.action);
}
},
toggle: function () {
// Some actions here
var catId = this.$el.children('select').val();
// Options are available from any method in the view.
if (this.options.toggleCategories) {
App.trigger('toggleCategories', catId);
}
}
Upvotes: 1
Reputation: 55750
I feel that a view should not have any collection specific logic. The only thing it should be doing is to render the view based on the events fired.
So what I would do in this case is to bind
the common event on the SubView
initialize: function () {
_.bindAll(this, 'render', 'action');
this.collection.on('reset', this.render);
},
Which is common for both the pages.
And before the view is actually instantiated in its parent view..
AddView
initialize : function() {
this.collection = new App.Collections.Categories
this.collection.on('request', this.action);
},
new App.Views.CategoriesViews({
el: $('#select-box-cats'),
collection: this.collection
});
Upvotes: 0