Backbone save model issues - javascript

I'm trying to save a model and on success, unrender it:
problem is that from within success i can't reference the this reference (which is the view) and I also cannot reference the variable isOk.status that this.model.save(...) returns.
the code:
save: function(e) {
e.preventDefault();
var isOk = this.model.save(null,
{
wait: true,
success: function(model, response){
console.log(response);
console.log(response.status);
},
error: function(model, response){
console.log("error");
console.log($.parseJSON(response.responseText));
$('#errorMessage').empty();
$('#errorMessage').append($.parseJSON(response.responseText).error);
$('#errorApproveModal').modal({
keyboard: true
});
}
});
console.log('logging isOk');
console.log(isOk);
//this one is working! It's on validate event
if(!isOk){
$('#errorMessage').empty();
$('#errorMessage').append("Error: there was an error");
$('#errorApproveModal').modal({
keyboard: true
});
return false
}
console.log(isOk);
**//both those checks are not working for some reason.**
//
if(isOk.status == 200 || isOk.statusText == "OK"){
console.log('in is ok');
this.remove();
}
return false;
}
Btw the view is:
App.Views.User = Backbone.View.extend({
model: App.Models.User
,
save: function...
});
Can someone please help?
Is there a better way to handle the success and error than this method?
Thanks!!
Roy

I'm not sure if this is the proper way to do it but I always just declare a variable referencing this from the view's function, then use that in success. Something like this:
save: function(e) {
// ADD THIS LINE
var me = this;
var isOk = this.model.save(null,
{
....
success: function(model, response){
// USE me IN HERE
me.render(); // e.g
},
....
}

You also can do this:
save: function(e) {
var isOk = this.model.save(null,
{
....
success: function(model, response,options){
// USE me IN HERE
this.options.me.render(); // e.g
},
//ADD me this
me : this
....
}
With the options,you can do all your parameters.

Related

How to skip parse function call in backbone model while calling fetch

I have a backbone model which has custom parse function, while calling the fetch on this model sometimes I wanted to skip the parse function in certain scenarios. How can I do it. I tried the following option which did not work.
myModel.fetch({
parse: false,
success: _.bind(function(model, response) {}, this),
error: _.bind(function(model, response) {}, this)
});
My model code:
var MyModel = BaseModel.extend({
initialize: function() {
console.log('EventCloneModel in initialize()');
_.extend(Backbone.Model.prototype, Backbone.Validation.mixin);
},
url: function() {
var url = gc.apiUrl;
var locale = "en_US"
url += '&locale=' + locale;
return url;
},
parse: function(response) {
//some parsing logic goes here
return response;
},
getValidations: function(){
return this.validation;
}
});
return MyModel;
});
Put the skip condition in your parse function. How you determine the skip condition is up to you.
parse: function(response) {
if(skipParse)
return response;
//parse the response here. If the code reaches this point,
//it means you want to parse it.
return response;
},

Backbone / Facebook API not working as expected?

In my index.html I call the Facebook SDK. In there I have the following code that triggers a controller in my Backbone application.
The trigger runs a function that calls the FB.api() that gets the logged in user.
The first example of backbone code works fine, but the second has a middle function that I pass the data to, but it gives me an error back from facebooks all.js file which is minified.
The reasons for wanting the middle function is to be able to fire them in different orders later on.
Facebook SDK:
FB.Event.subscribe("auth.statusChange", function (response) {
MyApp.trigger("fb:initialize", response);
});
backbone.js controller code WORKING:
initialize: function() {
App.on("fb:initialize", this.getUser);
},
getUser: function(event) {
if (event.status === "connected") {
FB.api("/me", function (response) {
if (response && !response.error) {
console.log(response);
}
});
} else {
//do nothing
}
}
backbone.js controller code NOT WORKING:
initialize: function() {
App.on("fb:initialize", this.testFunction);
},
testFunction: function(event) {
var status = event.status;
this.getUser(status);
},
getUser: function(status) {
if (status === "connected") {
FB.api("/me", function (response) {
if (response && !response.error) {
console.log(response);
}
});
} else {
//do nothing
}
}
I have tried so far using what I think is called "closures". As the FB.api() is asynchronous, this relates to the window instead of the current object. So I tried setting a variable to this outside the call. But it also doesn't work.
For example:
var oThis = this;
var apiString = '/' + this.model.id + '/photos';
FB.api(apiString, function(response){
loadPhoto(response, 1, oThis.model);
});
Try
initialize: function() {
var _this = this;
App.on("fb:initialize", function(event) {
_this.getUser(event.status);
});
},
getUser: function(status) {
if (status === "connected") {
FB.api("/me", function (response) {
if (response && !response.error) {
console.log(response);
}
});
} else {
//do nothing
}
}
or alternatively use underscore's .bind() to always bind to the right this. http://underscorejs.org/#bind
Try to use listenTo instead of App.on. Something like that:
this.listenTo(App, 'eventName', (function(_this) {
return function() {
return _this.getUser();
};
})(this));

How to optimize (minimize) jQuery AJAX calls

I have over 50 AJAX calls from different functions of my code. All these calls have a similar structure with different data/url/callback params:
var jqXHR = $.post('/dba/port.php', {
mode: "del_wallfunds",
pdata: cdata,
wname: wName
},
function (data) {}, "json")
.done(function (data) {
var msg = data.msg;
if (msg.indexOf("Error") == -1) {
alertify.success(msg);
delSelected(selGroup);
} else {
alertify.error(msg);
}
})
.fail(function () {
alertify.error("Error .....");
});
I am thinking how to write a function that would return that var jqXHR to minimize the total size of the code. It is not a problem to pass all static variables like URL, error strings etc. But the problem is that all callback functions on ".done" are different and I don't know how to pass these callback functions as variables.
One way would be to call a single "universal" function on .done and pass a "switch" variable to that function, but it doesn't seem to be an elegant solution.
Any suggestions how to it in some elegant way?
Thanks
Either pass the done callback function as an argument when calling your function:
function ajaxCall(url, data, doneCallback) {
return $.post(url, data, doneCallback, "json").fail(...);
// or
return $.post(url, data, function() {}, "json").done(doneCallback).fail(...);
}
var jqXhr = ajaxCall('yoururl.php', {key: 'value'}, function(data) {
// do something
});
Or return the jqXhr object from the function, and assign the done callback then:
function ajaxCall(url, data) {
return $.post(url, data, function() {}, "json").fail(...);
}
var jqXhr = ajaxCall('yoururl.php', {key: 'value'});
jqXhr.done(function(data) {
// do something
});
Alternatively switch to using jQuery.ajax() instead, and pass the entire options object in:
function ajaxCall(options) {
return $.ajax(options).fail(...);
}
var jqXhr = ajaxCall({
url: 'yoururl.php',
data: {key: 'value'},
dataType: 'json'
});
jqXhr.done(function(data) {
// do something
});
You can try to :
turn "request successfully returned a treatment error" into a "rejected request",
put the "alertify" processing in a common callback
Here is a sketch of what this could give :
function myAjaxApi(url, data){
var myAjaxCall = $.post(url, data, function (data) {}, "json")
.then(function (data) {
// using .then : change "request succesful with error state"
// to "rejected state"
var msg = data.msg;
if (msg !== undefined && msg.indexOf("Error") >= 0) {
var dfd = $.Deferred();
// try to match the same signature as the "error" option
dfd.reject(this, msg);
return dfd;
} else {
return data
}
});
myAjaxCall.done(function(data){
if (data.msg) {
alertify.success(data.msg);
}
}).fail(function (jqxhr, msg) {
if (!msg) { msg = "Error ....."; }
alertify.error(msg);
});
return myAjaxCall;
}
//usage
myAjaxApi('/dba/port.php', {mode: "del_wallfunds", pdata: cdata, wname: wName})
.done(function (data) {
// the ".done()" queue will not be executed if msg contains "Error" ...
delSelected(selGroup);
});
Some parts should be written with more care ; the above example is meant to illustrate how you can wrap your repeated ajax calls inside a common api.

What if i set the model upon the success of model.save

I am doing the following
var model = new Backbone.Model; // some new model
inside collection :
this.bind("change", this.onChange);
...... //
onChange: function( model, options ) {
model.save(null, {
error : function() {
console.log('error');
},
success: function() {
model.set( someNewData );
console.log('done');
}
});
},
In this case the browser sends two requests for updating the data.
First one for model.save() and second for model.set().
Why is this so? In general when i do model.set() it will NOT send the request to server.. But when i do the same inside the success callback in side model.save(), then model.set() also sends the request.
Why this is so?
and how to avoid it?
If you want to prevent the change event being triggered, you can pass a silent: true option to the set method:
model.set(someNewData, {silent: true});
And a demo http://jsfiddle.net/nikoshr/eekdb/6/
If you want the event but still want to cancel the save, you could pass a custom option to the set method. For example, a fromsuccess attribute:
var M = Backbone.Model.extend({
initialize: function() {
this.on('change', this.onChange);
},
onChange: function (model, options) {
if (options && options.fromsuccess)
return;
model.save(null, {
success: function () {
model.set({
data: 'data'
}, {fromsuccess: true});
}
});
}
});
http://jsfiddle.net/nikoshr/eekdb/7/

Extending jQuery ajax success globally

I'm trying to create a global handler that gets called before the ajax success callback. I do a lot of ajax calls with my app, and if it is an error I return a specific structure, so I need to something to run before success runs to check the response data to see if it contains an error code bit like 1/0
Sample response
{"code": "0", "message": "your code is broken"}
or
{"code": "1", "data": "return some data"}
I can't find a way to do this in jQuery out of the box, looked at prefilters, ajaxSetup and other available methods, but they don't quite pull it off, the bets I could come up with is hacking the ajax method itself a little bit:
var oFn = $.ajax;
$.ajax = function(options, a, b, c)
{
if(options.success)
{
var oFn2 = options.success;
options.success = function(response)
{
//check the response code and do some processing
ajaxPostProcess(response);
//if no error run the success function otherwise don't bother
if(response.code > 0) oFn2(response);
}
}
oFn(options, a, b, c);
};
I've been using this for a while and it works fine, but was wondering if there is a better way to do it, or something I missed in the jQuery docs.
You can build your own AJAX handler instead of using the default ajax:
var ns = {};
ns.ajax = function(options,callback){
var defaults = { //set the defaults
success: function(data){ //hijack the success handler
if(check(data)){ //checks
callback(data); //if pass, call the callback
}
}
};
$.extend(options,defaults); //merge passed options to defaults
return $.ajax(options); //send request
}
so your call, instead of $.ajax, you now use;
ns.ajax({options},function(data){
//do whatever you want with the success data
});
This solution transparently adds a custom success handler to every $.ajax() call using the duck punching technique
(function() {
var _oldAjax = $.ajax;
$.ajax = function(options) {
$.extend(options, {
success: function() {
// do your stuff
}
});
return _oldAjax(options);
};
})();
Here's a couple suggestions:
var MADE_UP_JSON_RESPONSE = {
code: 1,
message: 'my company still uses IE6'
};
function ajaxHandler(resp) {
if (resp.code == 0) ajaxSuccess(resp);
if (resp.code == 1) ajaxFail(resp);
}
function ajaxSuccess(data) {
console.log(data);
}
function ajaxFail(data) {
alert('fml...' + data.message);
}
$(function() {
//
// setup with ajaxSuccess() and call ajax as usual
//
$(document).ajaxSuccess(function() {
ajaxHandler(MADE_UP_JSON_RESPONSE);
});
$.post('/echo/json/');
// ----------------------------------------------------
// or
// ----------------------------------------------------
//
// declare the handler right in your ajax call
//
$.post('/echo/json/', function() {
ajaxHandler(MADE_UP_JSON_RESPONSE);
});
});​
Working: http://jsfiddle.net/pF5cb/3/
Here is the most basic example:
$.ajaxSetup({
success: function(data){
//default code here
}
});
Feel free to look up the documentation on $.ajaxSetup()
this is your call to ajax method
function getData(newUrl, newData, callBack) {
$.ajax({
type: 'POST',
contentType: "application/json; charset=utf-8",
url: newUrl,
data: newData,
dataType: "json",
ajaxSuccess: function () { alert('ajaxSuccess'); },
success: function (response) {
callBack(true, response);
if (callBack == null || callBack == undefined) {
callBack(false, null);
}
},
error: function () {
callBack(false, null);
}
});
}
and after that callback success or method success
$(document).ajaxStart(function () {
alert('ajax ajaxStart called');
});
$(document).ajaxSuccess(function () {
alert('ajax gvPerson ajaxSuccess called');
});

Categories

Resources