Reputation: 3764
I'm building a backbone app using backbone-relational models (but that shouldn't matter for this question).
Basically, I have an edit button that will display a hidden div. Inside the hidden div id a sub-view (called DetailsView
) that renders table elements to populate a list of users. My model (for the whole app) looks roughly like this:
{ 'id': 'foo',
'users':
{
'username': 'bobby',
'password': 'peanuts'
},
{
'username': 'sally',
'password': 'watermellon'
}
}
In my main view (that is fed by a collection of the above models), when the user clicks the edit button, this is triggered:
edit: function(){
var userModels = this.model.get('users'),
detailViewContainer = this.$('tbody.users');
console.log(name + ' has ' + userModels.length + ' models');
//clear out eveything in tbody.users to prevent dupes
detailViewContainer.html('');
//check if there are actually user models
if(userModels.length > 0){
userModels.forEach(function(user) {
var details = new DetailsView({model: user});
details.render();
detailViewContainer.append(details.el);
});
}
The code smell comes from the fact that I have to declare that detailViewContainer
explicitly.
Originally, in my forEach loop would call another function in the view that contained the code to declare and render the DetailsView
. However, I would loose the context of this
.
My original code looked something like this:
edit: function() {
var userModels = this.model.get('users'),
detailViewContainer = this.$('tbody.users');
console.log(name + ' has ' + userModels.length + ' models');
//clear out eveything in tbody.users to prevent dupes
detailViewContainer.html('');
//check if there are actually user models
if(userModels.length > 0){
userModels.forEach(function(user) {
this.renderDetailsView;
});
}
},
renderDetailsView: function(user) {
var details = new DetailsView({model: user});
this.$('tbody.users').append(details.render());
},
In the renderDetailsView
, I would loose context of this
and could not append the DetailsView
to the proper DOM element (the view would append to all of the tbody.users
DOM elements , as the this
context became the window since it was in a loop).
Having to explicitly declare a detailsViewContainer
seems hacky to me, and I'd like to be able to keep the this
context pointing to the main view, not the entire window.
The DetailsView
template just a set of <tr><td></td></tr>
elements. Is there a better way to embed this view without having to resort to creating the detailViewContainer
?
(One possible option was having the DetailView
loop through the collection returned from this.model.get('users')
all by itself... is that a good idea?)
Upvotes: 0
Views: 513
Reputation: 1145
If you're doing what you're doing because of the loss of 'this,' you can pass your context to forEach.
userModels.forEach(function(user) {
this.renderDetailsView();
},this);
Now you have the proper 'this' available to you. Hope this helps.
Upvotes: 2