Reputation: 10740
I have a collection that already filled with models and I need to update this collection with one more model and show it (model) on the page. So, following the docs, I get model from server in the view:
this.collection.fetch(
{
add: true,
data: FILTER + '&page=' + (CURRENT_PAGE + 1),
success: function(response){}
});
But this new model doesn't show up on the page, but the collection gets new model. I suppose that some method of the collection has to be fired, but it does not.
Sorry in advance, newbie in Backbone)
The view:
var EcoNatureCardInListView = Backbone.View.extend({
tagName: 'tr',
className: 'nature-card-tr',
template: $('#natureCardsListTR').html(),
render: function(){
var tmpl = Handlebars.compile(this.template);
this.$el.html(tmpl(this.model.toJSON()));
return this;
}
});
var EcoNatureCardsListView = Backbone.View.extend({
el: $('#nature-cards-wrapper'),
events: {
"click a.short-eco-entity": "showFullEcoNatureCard",
"click #add-cards": "addCardsOnPage"
},
initialize: function(){
$("#nature-cards-list").html("");
this.collection = new EcoNatureCardCollection();
this.collection.fetch({
success: function(response){}
});
this.collection.on('reset', this.render, this);
this.collection.on('add', this.add, this);
},
render: function(){
var that = this;
_.each(this.collection.models, function(item){
that.renderEcoNatureCard(item);
}, this);
$(addCards).show();
$("#total-objects").text(TOTAL_OBJECTS);
$("#filtered-objects").text(FILTERED_OBJECTS);
if (this.collection.length < 20){
$(addCards).hide();
}
},
renderEcoNatureCard: function(item){
var ecoNatureCardInListView = new EcoNatureCardInListView({
model: item
});
$('#nature-cards-list').append(ecoNatureCardInListView.render().el);
},
showFullEcoNatureCard: function(e){
var _id = $(e.currentTarget).attr('value');
var natureCard = ecoNatureCardsListView.collection.where({ _id: _id })[0];
if (typeof(fullEcoNatureCardView) === 'undefined'){
fullEcoNatureCardView = new FullEcoNatureCardView(natureCard);
} else {
fullEcoNatureCardView.initialize(natureCard);
}
},
addCardsOnPage: function(){
this.collection.fetch({
add: true,
data: FILTER + '&page=' + (CURRENT_PAGE + 1),
success: function(response){}
});
},
filterDocs: function(FILTER){
$("#nature-cards-list").html("");
//$(loading).show();
this.collection.fetch({
data: FILTER,
success: function(response){}
});
}
});
P.S. version 0.9.2
Upvotes: 2
Views: 3897
Reputation: 753
I think your issue is that your view only subscribe to the "reset" event of the Collection, which is not triggered when you call fetch with the add:true option. In this case it will only trigger an "add" event, so you need to listen to that as well. What I generally do is that I have
this.collection.on('reset', this.render, this);
this.collection.on('add', this.renderEcoNatureCard, this);
In my view's initialization function, and the view's render function calls the add function for each model of the collection.
P.S.: with Backbone 0.9.2 I think that you have to use .on(...) as listenTo wasn't there yet.
Upvotes: 2
Reputation: 54821
You need to render when the collection is changed. I never used reset
so I'm not sure when it's fired.
Change
this.collection.on('reset', this.render, this);`
to
this.listenTo(this.collection,'add remove',this.render);
Try not to use on(..)
for Views. Otherwise you have to call off(..)
when the View is removed. When you use listenTo
the View will take care of removing events when it's destroyed.
EDIT:
You do not have to declare a local reference to this
when using Underscore.js.
Change:
var that = this;
_.each(this.collection.models, function(item){
that.renderEcoNatureCard(item);
}, this);
To:
_.each(this.collection.models, function(item){
this.renderEcoNatureCard(item);
}, this);
When you use callbacks in Underscore.js the parameter after the function reference is the context
. That is the object space the function will be executed in. You were always telling it to run the function using this
.
Upvotes: 2