When a fetch is called (in response to a user’s action) after an initial fetch, many of the newly fetched models can be similar to the existing models from the initial fetch. If I call fetch with the add: true option, there can be duplicate models in the collection.
Problem: Instead of removing all existing models (say with id=1,2,3,4) from the collection and inserting the newly fetched models (id=1,2,3,5), is it possible to do the following 2 operations:
-
Add only the new models
id=5, resulting in a collection withid=1,2,3,4,5. Then render only the new Views (id=5) -
Add the new models
id=5and remove the models not found in the newfetch(id=4). Then render the new Views (id=5) and remove the old Views (id=4)
Attempt:
Instead of calling App.listingCollection.fetch(), the fetchNew() function is used. This works to only add the new models id=5 to the collection.
How should the rendering of the new views only (id=5) be triggered without re-rendering the existing views id=1,2,3,4? I tried this with the line new ListingMarkerView({ model:item }).render(); within ListingCollection, but I get an error responding to the line var marker = L.marker([this.model.get('lat'), this.model.get('lng')]); in ListingMarkerView :
Error
Uncaught TypeError: Object #<Object> has no method 'get'
Collection
ListingCollection = Backbone.Collection.extend({
model: Listing,
url: '/api/search_by_bounds',
fetchNew: function(options) {
options = options || {};
var collection = this,
success = options.success;
options.success = function(resp, status, xhr) {
_(collection.parse(resp, xhr)).each(function(item) {
// added this conditional block
if (!collection.get(item.id)) {
collection.add(item, {silent:true});
new ListingMarkerView({ model:item }).render();
}
});
if (!options.silent) {
collection.trigger('reset', collection, options);
}
if (success) success(collection, resp);
};
return (this.sync || Backbone.sync).call(this, 'read', this, options);
}
});
View
ListingMarkerView = Backbone.View.extend({
render: function() {
var marker = L.marker([this.model.get('lat'), this.model.get('lng')]);
markers.addLayer(marker);
},
close: function() {
this.unbind;
}
});
A restful API has no concept of state of the clients it’s speaking to, therefore when making a
GETrequest to retrieve a list of objects (e.g. http://example.com/restapi/user/), the rest server should ALWAYS return a full list of the matching objects.On the Backbone end, you should then just
.resetyour collection with the list from the server..resetwill empty the collection and then add all the items, like:This way you don’t get collisions and you don’t have to worry about anything. Except if you’ve got models you’ve changed in the collection locally that haven’t been saved back to the server.
If you’re looking for a way to prevent modification of local items within a collection, that will need something like the sorcery you’re speaking of above.