I have UserModel
: UserView
and UserCollection
: UserCollectionView
. With this, I am trying to bind a click
event
The main problem is that you are rendering all UserView views in the same container:
$('#users-list').append(this.template(this.model.toJSON()));
This is why the click event selector('click .user-data') is selecting the other UserView buttons and firing it's clicks too.
You didn't ask but... here it goes some suggestions:
Here is a jsfiddle with what I think you want: https://jsfiddle.net/Neviton/n52j873u/
There are many issues with your code.
Main problem is that, all your userView's are pointing to the same selector, and the element matching this selector .user-box-wrapper
is inside the view template - So whenever you create a new userView, it'll add a new event listener to .user-box-wrapper
present in all existing userViews, but not to itself. So your first userView will have n-1
events handlers registered to it while last one has none (n
being total number of userViews). View element is not supposed to be part of template, template is supposed to be added to the view element.
When your view will have multiple copies of itself, don't define el
option, let backbone create a new element for each instance of the view. You can customize the properties of this element.
Another issue is that you are not appending the userView template to your userView element, but something else outside it ($('#users-list')
. So clicking the template won't trigger the event handler (in your case this is why you're last userView doesn't fire it's event. It was bound to all other existing views because common selector was provided by el
)
You should try to avoid global selectors like $('#users-list')
from within a view. In this case you can append the userView to #users-list
from within userCollectionView who's el points to #users-list
.
Your code should be:
var root = 'http://localhost:5000/api/v1';
var app = {};
// Backbone Model
app.UserModel = Backbone.Model.extend({
defaults: {
// urlRoot: root + '/users',
name: 'Default Name',
email: '30',
username: 'default_username'
},
initialize: function() {
this.set({
id: this.get('username')
});
console.log('User model \'' + this.id + '\' has been initialized.');
}
});
// Backbone Model View
app.UserView = Backbone.View.extend({
className: 'user-box-wrapper',
/*--^-- creates a new div with this class for each user*/
template: _.template($('#connections-user-template').html()),
events: {
'click .user-data': 'userClicked'
},
initialize: function() {
this.render();
},
render: function() {
this.$el.append( this.template( this.model.toJSON()));
console.log('User view is rendered');
},
userClicked: function(ev) {
console.log("User selected");
// console.log(ev.currentTarget);
}
});
// Backbone Collection
app.UserCollection = Backbone.Collection.extend({
model: app.UserModel,
url: root + '/users',
initialize: function() {
// this.fetch();
},
parse: function(data) {
// console.log(data.data);
return data.data;
}
});
// Backbone Collection View
app.UserCollectionView = Backbone.View.extend({
el: '#users-list',
template: _.template($('#connections-template').html()),
initialize: function() {
this.connections = new app.UserCollection();
var self = this;
this.connections.fetch().done(function() {
self.render();
});
},
render: function() {
this.$el.html(this.template());
console.log('User collection view is rendered');
this.connections.each(function(user) {
console.log('User : ' + user.get('id'));
var userView = new app.UserView({
model: user
});
this.$el.append(userView.el); /*append child view here*/
},this);
}
});
var connectionsView = new app.UserCollectionView();