How do I trigger the success callback on a model.save()? - backbone.js

this.model.save({
success: function(model, response){
console.log('success');
},
error: function(){
console.log('error');
}
})
The model is correctly posted to the server which handles the save, but the success callback is not fired. Do I need to send something back from the server ?

The first argument of save is the attributes to save on the model:
this.model.save( {att1 : "value"}, {success :handler1, error: handler2});

For some unknown reason, none of the above method worked for me. The api only was not hit in my case.
But later while searching on this, I bumped into this link, where some one had tried null instead of {} as the first parameter.
this.model.save(null, {
success: function (model, response) {
console.log("success");
},
error: function (model, response) {
console.log("error");
}
});
so, this worked for me. Hope this helps you too.

Your server must return a JSON object. If the response is not a JSON object, the callbacks will not fire.
If for success your server doesn't return a JSON object, perform a save with dataType:"text" option, like this:
this.model.save([],{
dataType:"text",
success:function() {},
error:function() {}
});
With this option it will not be waiting for a JSON in response, but a text, and thus the callback will be launched.

You may use underscore lib as follows as backbone already depends upon this. Remember first argument of save must either have attributes or you may just pass {} in case you want to save model itself.
this.model.save({}, _.bind(function(model, response){
//Do whatever you want e.g.
this.collection.add(model)
}, this))

so im a little confused - do i still need to pass in all attributes in order for me to call a save event? what if my model is large.. i dont wish to set every property manually
im calling model.save and attempting to do the following:
this.model.save(
{
success: function (model, response) {
console.log('model saved');
}
});
ok just to answer my own question incase anyone finds this post, i did the following which works:
this.model.save({ id: this.model.get('id') },
{
success: function (model, response) {
console.log("success");
},
error: function (model, response) {
console.log("error");
}
});
EDIT: I couldn't reply to you for some reason, but I can edit
but you don't have to set id: this.model.get('id') you can just pass a blank object because a blank attribute just won't extend attributes, does nothing:
this.model.save({}, {
success: function (model, response) {
console.log("success");
},
error: function (model, response) {
console.log("error");
}
});

The following is the code that i am using for backbone model save.
this.model.save(model,{
success:function(model){
console.log("Saved Successfully");
},
error:function(model){
console.log("Error");
}
});
Cheers
Roy M J

For those that want to save a model, without updating the attributes, you can do the following:
model.once("sync", function(model, response, options){
//
});
model.once("error", function(model, response, options){
//
});
model.save();

In you initialize function, bind the sync method to a method you define (onSaveSuccess)
initialize: function (options) {
this.model.on('sync', _.bind(this.onSaveSuccess, this));
},
onSaveSuccess: function() {
console.log('saved');
this.render();
},
This way, any time you run this.model.save(), it will run the onSaveSuccess function as a callback if your sync is successful

Related

How do I examine xhr objects and models from error messages in a backbone save request?

Below is an example function of a model being saved, and the error handling involved. I want to put control flow in the error handling so for specific types of errors one thing happens and for another type of error, another thing happens, but I can't seem to examine the xhr with console logs or debugger.
propChange: function (newName) {
var self = this;
var oldProp = this.model.get('prop');
this.model.save({ name: newProp }, {
success: function (data, textStatus, xhr) {
...
},
error: function (model, xhr) {
//I can't console.log anything hear, use debugger, or put a break point here so how do I investigate or experiment with what model and xhr could be at this point?
}
});
},

DropzoneJs success and error callback

I'm building an AngularJs app and I'm using a dropzone from DropzoneJs. I need to use the success and error callback because I have to access to the server response. I'm having a problem that if I use the callbacks, the previewTemplate changes... So, can I change the previewTemplate inside the callback?
If I don't use the callbacks here's the result template and the code:
var myDropzone = $("#storageDropzone").dropzone({
url: firstUrl,
});
If I use the callbacks the "tick" or the "cross" don't show up:
var myDropzone = $("#storageDropzone").dropzone({
url: firstUrl,
error: function (file, response) {
console.log("Erro");
console.log(response);
},
success: function (file, response) {
console.log("Sucesso");
console.log(response);
},
complete: function (file) {
console.log("Complete");
}
});
So, can I change the previewTemplate inside the callbacks? or simply, keep the one that exists?
So, this is the workaround I found...
Instead of using the callbacks, I make the changes on the init function. Although this answer doesn't satisfy me, it's the best I can do for now... If anyone can explain why it works on the init but not as a callback feel free to answer.
This is the solution:
var myDropzone = $("#storageDropzone").dropzone({
init: function () {
this.on("processing", function (file) {
$scope.$apply($scope.working = true);
this.options.url = lastUrl;
$scope.$apply($scope.processing = true);
});
this.on("success", function (file, response) {
console.log("sucesso");
var ficheiro = { nome: file.name, link: response[0] };
$scope.$apply($scope.uploadedFiles.push(ficheiro));
});
this.on("error", function (file, error, xhr) {
var ficheiro = { nome: file.name, status: xhr.status, statusText: xhr.statusText, erro: error.message };
$scope.$apply($scope.errorFiles.push(ficheiro));
});
}
I think what is happening is that since you are overriding the default DropZone "error" and "success" callback functions, the "tick" and "cross" are not created on the file upload tiles. It isn't that the template is changed; you are overriding the default DropZone error and success behaviors. For the "tick" and "cross" to show up, you would need to copy the code from the default DropZone error and success callback functions into your functions, then implement whatever additional or changed behavior you need.

Backbone.js Work with server response to save() method

I'm kind of new to Backbone. I need use the data in the server response to a save() method but I'm not sure how to get it. This is the code:
$(".act_btn").on("click", function(){
var act_id = $(this).attr("data-id");
startRecordItem = new StartRecordItem({
activity: act_id,
});
startRecordItem.save({
success: function(response){console.log(response)}
});
/*
recordItem = new RecordItem({
id: ... <---- I have to populate this with the data from the server response.
});
*/
Right now the success function doesn't work at all, what am I missing? I'd like to get an attribute from the JSON response and then use it on the ´new RecordItem´. The save itself works correctly and the response looks like this:
{"activity": 1, "id": 14}
What you're missing is that the first argument of .save. is the attributes that get passed into the model, pre-save. You want to do something more like this:
startRecordItem.save(null, {
success: function(response) {
console.log(response);
}
});
Since Backbone fires a sync event on successful save, you could also do this:
this.listenTo(startRecordItem, 'sync', function() { /* logic here */ });

parseJSON(response) is null

I have a Backbone model that is making a successful server request. The callback is using backbone's trigger method to trigger an event in the associated view, and its passing the parsed json response from the server request as the second parameter of the trigger method, as described in the backbone documents. In the view, the event triggers the render method, but the response object is null in the view. It's throwing this error
Uncaught TypeError: Cannot read property 'word' of null
Can anyone see what I might be doing wrong?
The server request from the model
new: function() {
var _this = this;
console.log("new function of model");
$.ajax({
url: "/gamestart",
type: "GET",
success: function(response) {
console.log(response);
var json = $.parseJSON(response);
_this.set({lost: false});
_this.set({win: false});
_this.trigger("gameStartedEvent", json);
}
})
},
the event in the initializer method of the view which triggers the render method to render the response
this.model.on("gameStartedEvent", this.render, this);
the render method where the response is null
render: function(response) {
$("#hint").show();
console.log(response);
var html = this.template({characters: response.word});
this.el.hide();
this.el.html(html).show();
},
Note, if it matters, the view is being instantiated with the model
var word_view = new WordView({model: game})
Update
Actually the error's happening here. The response is returning successfully but i'm parsing it incorrectly. The variable json is null when I check the console. Can you see what I'm doing wrong?
var json = $.parseJSON(response);
console.log(json)
Response
Object {word: Array[6]}
word: Array[6]
__proto__: Object
There was actually no need to call parseJSON on the response object. I could get the word property directly off the response object, so I just passed the response object as the second argument to trigger, and called response.word in the view.
$.ajax({
url: "/gamestart",
type: "GET",
success: function(response) {
console.log(response.word);
var json = $.parseJSON(response); ####unnecessary to parseJSON here
console.log(json);
_this.set({lost: false});
_this.set({win: false});
_this.trigger("gameStartedEvent", response);
}
})
},

How to get a good response from saving a model

With backbone.js I'm saving a model. A PUT is send to the server and the response is returned. The first time I do it, it returns success, the following times an error is return, because after the first time the response is added to the model.
Save function in Backbone.js:
saveCountry: function() {
this.model.save({},{
success: function(model, response) {
console.log('success! ' + response);
},
error: function(model, response) {
console.log('error! ' + response);
}
});
this.render();
return false;
},
PHP returns a JSON-string:
{"response": "Model saved!"}
Following PUT's get an error as response, because 'response' is added to the model:
Unknown column 'response' in 'field list'
Why is the response added to the model and how do I prevent it?
From Backbone's documentation on model save:
Set a hash of model attributes, and sync the model to the server. If
the server returns an attributes hash that differs, the model's state
will be set again.
http://documentcloud.github.com/backbone/docs/backbone.html#section-41
What to do to make it work: don't return {"response": "Model saved!"} from the server. Just return a success (status 200) with no content.
If the save did not work, return a JSON with the errors, and Backbone will trigger an error event on your model, with the JSON you provided (see http://documentcloud.github.com/backbone/docs/backbone.html#section-41 and http://documentcloud.github.com/backbone/docs/backbone.html#section-145).
Just to resurrect an ancient thread...
It isn't always possible/desirable to change the response you get back from the server.
Another solution is to override parse in the model to take care of this. For your situation, where the response is inappropriate for ALL of your models, you could do it in a superclass.
MyModel = Backbone.Model.extend({
parse: function(data) {
delete data["success"];
return data;
}
});
Address = MyModel.extend({
saveCountry: function() {
this.model.save({},{
success: function(model, response) {
console.log('success! ' + response);
},
error: function(model, response) {
console.log('error! ' + response);
}
});
this.render();
return false;
},
...
});

Resources