Is silent model destroy possible - backbone.js

Is it possible to do a silent destroy on a model? I've tried
model.destroy({ silent: true });
This will not remove the model from the collection. If this shouldn't be possible, how can the same effect be attained?

You can use .remove to remove the model from the collection
collection.remove(model, { silent: true });
This will remove the model from the collection, but will never destroy it on the server ( will not send DELETE request.

Related

Appending new data to the Backbone Relational Relation

I'm trying to design a load more type of system where every time you press load more you add data to the existing collection. This is a rough sketch of how the UI looks.
Everything works pretty great except as you would except everytime I re-run the
items.fetch
What it does: It overrides the entire collection with the new data
What I want it to do: I want the new records returned to be added to the records collection not override old 'records'
How can I make this work so that the newly fetched records are appended to existing records and not overridden?
Add { remove: false } to your fetch call:
items.fetch({ remove: false, data: { nextId: this.info.get('nextId') } });
What's happening here is Collection#fetch will synchronize its models with the data the server returns. That includes adding new models, updating models already present, and removing models that are not included in the response.
The behavior of fetch can be customized by using the available set options. For example, to fetch a collection, getting an "add" event for every new model, and a "change" event for every changed existing model, without removing anything: collection.fetch({remove: false})
The available set options are add, remove, and merge. Setting one (or all) to false will disable that functionality in the fetch.
It sounds like you just want { remove: false }, leaving the add and merge functionality.
I'm not familiar with backbone-relational,
But with a normal collection, you can do the following in parse method:
Backbone.Collection.extend({
parse: function(response){
// you can update the info here like this.info = response.info or similar
return _.union(this.toJSON(), response.records);
}
});
Basically we combine the response with existing data and return it so that we maintain the previous data when the collection updates

View event reflected in collection convention

What is the best way to remove a model from a collection that has been removed in the DOM. Let me ask a better question, how do I keep views in sync with a collection?
remove the view first, while removing execute
this.model.collection.remove(this.model);
you can check with conditions to whether current view has a model, and that model has a collection etc before you execute the same.
I've followed the backbone Todos example application. This keeps view state up to date with collection.
Pass models to any view created like so:
var someView = new SomeItemView({ model: modelFromCollection });
Then listen to events on that model and react from the view:
initialize: function() {
this.listenTo(this.model, 'destroy', this.remove);
// listen to other events ...
}

Collection fetch from server, not firing change when model has been delete from server

I am fetching a collection from the server, lets say I originally start with 30 models and in the database one of these models has some of attributes changed, when I fetch the collection the change is detected and the changes are rendered. Fine works just fine.
But when the model is delete in the database and the collection which had 30 and now has 29 does not fire destroy on the missing model. The model does not exist anymore but the view is still rendered and it does not correspond to any model, because the model is not part of the collection anymore. Need help with this one. And the view is binded to "change" and also "destroy".
I already tried all kinds of stuff, many variations in code and nothing seems to work.
Thanks
var commentCollection = new CommentList;
commentCollection.fetch({ data: $.param({ user_id:id}), success: function(){
Profile_view = new Profile({collection: commentCollection});
$("div.Profile_container").html(this.Profile_view.el);
} });
function fetch_collection(commentCollection, id){
//commentCollection.reset();
commentCollection.fetch({update: true, data: $.param({ user_id:id})});
console.log(commentCollection)
}
setInterval(function(){fetch_collection(commentCollection, id)},10000);
I got it!!!!!
All I had to do was bind the remove event to the view function that removes the actual view from the DOM
this.model.bind("remove", this.close, this)

Debugging Backbone.js: rendering after collection fetch()

I'm trying to do basic render() after fetch() on collection (Backbone 0.9.2):
var ProjectListView = Backbone.View.extend({
el: $('#container'),
initialize: function () {
this.collection = new ProjectsCollection();
this.collection.bind("change", _.bind(this.render, this));
this.collection.fetch({ success: function () { console.log("collection fetched"); } });
...
},
render: function () {
console.log("rendered");
...
Creating new View instance prints out:
collection fetched
So the render() never gets called after fetch(). What am I doing wrong here? There are no exceptions present.
Any tips how to debug these sort of things in backbone?
Ps.
It seems that this feature is poorly documented given the number of questions on SO.
From the fine manual:
fetch collection.fetch([options])
Fetch the default set of models for this collection from the server, resetting the collection when they arrive. [...] When the model data returns from the server, the collection will reset.
And what does reset do? reset does this:
reset collection.reset(models, [options])
[...] Use reset to replace a collection with a new list of models (or attribute hashes), triggering a single "reset" event at the end.
So fetch calls reset to update the collection's models and reset triggers a "reset" event, not a "change" event. None of the models have changed and a collection's "change" events come from its models.
You should have render bound to "reset":
initialize: function () {
this.collection = new ProjectsCollection();
this.collection.bind("reset", _.bind(this.render, this));
this.collection.fetch(...);
}
If you want to listen for "change" events on the contained models then you can bind a "change" handler to the collection since:
You can bind "change" events to be notified when any model in the collection has been modified,
[...]
Any event that is triggered on a model in a collection will also be triggered on the collection directly, for convenience.
The collection will also generate "add" and "remove" events as the collection itself changes.
Newer versions of Backbone no longer reset collections during fetch:
When the model data returns from the server, it uses set to (intelligently) merge the fetched models, unless you pass {reset: true}, in which case the collection will be (efficiently) reset.
And set:
[...] performs a "smart" update of the collection with the passed list of models. If a model in the list isn't yet in the collection it will be added; if the model is already in the collection its attributes will be merged; and if the collection contains any models that aren't present in the list, they'll be removed. All of the appropriate "add", "remove", and "change" events are fired as this happens
So with newer versions of Backbone you'll want to list for the "add", "remove", and "change" events (which a collection based view should be listening for anyway); you could also use {reset: true} on the initial fetch and listen to "reset" as well. I'd recommend the following approach for collection based views:
Listen to "add" and handle that event with a callback that simply adds one item to the view, don't throw everything away and re-render.
Listen to "remvoe" and handle that event with a callback that only removes the newly removed model.
Listen to "change" and handle that with a callback that replaces (or updates) the appropriate item.
Listen to "reset" and bind that to render. Then pass {reset: true} to the collection's initial fetch call.
That will trap the important events and the collection-view will do the minimal amount of work to handle each one. Of course, this strategy isn't applicable to all situations but I think it is a good starting point.
This changed in 1.0
http://backbonejs.org/#changelog
"If you'd like to continue using "reset", pass {reset: true}."
Ok, so until some one can explain why binding didn't work, I used following workaround:
initialize: function () {
var self = this;
this.collection = new ProjectsCollection();
this.collection.fetch({ success: function () { self.render(); } });

Backbone - How to prevent models from being added to and removed from collections on server side validation failures

For example, if I do a destroy on a model and the server returns a 4xx/5xx, the error callback handler is called but the model is removed from the collection anyway. How I do prevent this from happening?
Backbone is optimistic about this starting in v0.9. From the docs at http://backbonejs.org/#upgrading
Creating and destroying models is now optimistic. Pass {wait: true} if you need the previous behavior of waiting for the server to acknowledge success. You can now also pass {wait: true} to save calls.
So all you have to do is set the {wait: true} flag in your save:
myModel.save(null, {wait: true});
or in your delete:
myModel.destroy({wait: true})

Resources