Backbone.js save error - backbone.js

I am scratching my head over an issue with backbone...
I have a backbone view, with an event which calls a function that saves the current model.
Its a simple form, in the view I do some validation before syncing the model.
this.model.save({
completed : completed,
company : company,
revenue : revenue,
term : term,
comments : comments,
probability : probability
},
{
success: function (model, response) {
console.log('success', model, response);
Evision.trackRouter.navigate("tracker/", {trigger: true});
},
error: function (model, response) {
console.log('error', model, response);
}
}
;
After success is fired it returns me back to my collection of models, where I can select another model to edit, its at this point when i attempt to save that i receive in my console and Chrome crashes.
If i expand this error it is indicating a problem with the function running the above, and my model is logged out in the console but when i try to expand it its empty?
Its worth saying that neither success or error is being fired ont he 2nd route round.
Thanks
Edit #1
Here is the error i receive before the crash
<error>
w.extend
w.clone
e.extend.toJSON
_.extend.save
_.extend.update
LocalStorage.sync
Backbone.sync
e.extend.sync
e.extend.save
Evision.Views.TrackerDetail.Backbone.View.extend.saveTracker
(anonymous function)
j
Edit #2 Here is my model
Evision.Models.Track = Backbone.Model.extend({
defaults: function() {
return {
id : Evision.trackerList.nextOrder(),
completed : false,
created : Utils.datestamp(),
company : "",
revenue : "",
term : "",
comments : "",
probability : "",
success : null
}
}
});

I know exactly the problem. I had this issue not so long back. First thing I looked at was the stack trace and just like in the comments above I was getting an extend problem with underscore. What you need to do is update backbone.js, underscore.js and backbone-localstorage.js(if you have it) to the most recent versions. The problem lies with versioning!

Turns out the issue was related to a modified version of Jerome's Backbone.localStorage, which would allow for both remote and local storage within the app. I replaced with the latest localStorage adapter and everything is working fine. Unfortunately I cant find the original source to notify.

Related

Unable to run a fetch operation in backboneJS

Here's a fetch operation I've written in a view:
this.collection.fetch ({
data:{
values: 100,
type: "normal"
},
success:(collection, response) => {
_.each(collection.models, (model) => {
Log.show(model.get("question"));
})
},
error: (err) => {
Log.error("couldn't receive data");
}
});
My Webstorm throws an error on fetch({}) that says Supplied Parameters are incorrect
I'm not able to find any other api specification for the fetch call. The code is in and the typescript definition for backbone I'm using is here:
https://github.com/borisyankov/DefinitelyTyped/blob/master/backbone/backbone.d.ts
UPDATE==
The result I see in the log is this:
Triple
Triple
Triple
Triple
Triple
Here "triple" is the value of the "question" attribute in the last model added to the collection. There are 5 models in the collection (in the persistent) database and if there were 6 it would display "Triple" 6 times. There is some problem in the API call I made to get the value of the question object
I'm probably not calling the function right. I need to know whats the appropriate call for getting the value of an attribute from the model. Or this could be a problem actually retrieving the values from the server.
I've tried the following to actually get the right value in the log:
Log.show(model.toJSON().question);
Log.show(model.toString());
Log.show(model.question);
The success callback should look like this:
success:function(collection, response){}

Backbone model's fetch doesn't work when the page initially loads but on second attempt works fine

In my backbone project I am trying to fetch a model based on some search criteria submitted by the users from a form. In submit handler, I am trying to fetch the model by passing search criteria's via data option (following is the code).
var productType=$("#productType").val();
var customerId=$("#customerId").val();
var stateSelected=$("#selectedState").val();
var srbStatus=$("#stateReportingStatus").val();
var dateType=$("#dateType").val();
var fromDate=$("#fromDate").val();
var toDate=$("#toDate").val();
var billTypeInd=$("#billTypeIndicator").val();
var dataElement=$("#dataElement").val();
var ediFileName=$("#ediFileName").val();
var ediBillName=$("#ediBillNumber").val();
var billId=$("#billId").val();
var claimantFirstName=$("#claimantFirstName").val();
var claimantLastName=$("#claimantLastName").val();
var insurerName=$("#insurerName").val();
var insurerFEIN=$("#insurerFEIN").val();
var insurerZip=$("#insurerZIP").val();
var dashboardSearchResultModel= new dashboardSearchResult();
var dashboardSearchResultModel= new dashboardSearchResult();
dashboardSearchResultModel.fetch({
data:{
productType: productType,
customerId: customerId,
state:stateSelected,
srbStatus:srbStatus,
dateType:dateType,
fromDate:fromDate,
toDate:toDate,
billTypeInd:billTypeInd,
dataElement:dataElement,
ediFileName:ediFileName,
ediBillName:ediBillName,
billId:billId,
claimantFirstName:claimantFirstName,
claimantLastName:claimantLastName,
insurerName:insurerName,
insurerFEIN:insurerFEIN,
insurerZip:insurerZip
},
wait:true,
success: function(dashboardSearchResultModel)
{
alert("This is what we get for result"+JSON.stringify(dashboardSearchResultModel));
$('#dashboardResultArea').html(self.dashboardResultTemplate({results:dashboardSearchResultModel.get("results")}));
},
error: function (model, xhr, options) {
alert("Error: An error occurred while trying to fetch the dashboardSearchResultModel");
alert("Error got model"+JSON.stringify(model));
alert("options:"+JSON.stringify(options));
alert("xhr:"+JSON.stringify(xhr));
}
});
Initially when the page loads after providing the search criteria's if I click submit the fetch doesn't work and goes to the error handler. After that when I submit the from second time the fetch works and retrieves data from the backend server. Any idea what is wrong? Thanks in advance.
When error callback is called, it is because your XHTMLRequest to the server returned a error (HTTP status code). So, there is where your problem resides.
Who starts this code? As the erros does not occur on a second attempt, I would suggest that you area callind $('#id').val() when the DOM is not ready. This way you are sending null values to the server, and that's causing the error you are receiving.
To solve your problem, assure you DOM is ready when executing this script.
See if your request is leaving the browser and reaching the server (i.e., cross-domain request fail with status 0, not reaching the server).
And, if it is, debug your server-side, as it does not seem to be an client-side problem.
So after trying many things I finally decided to try $.ajax call rather the fetch method. This is what I came up with
$.ajax({
type: "GET",
url: "rest/dashboardResult",
dataTyp: 'json',
data: {
productType: productType,
customerId: customerId,
state:stateSelected,
srbStatus:srbStatus,
dateType:dateType,
fromDate:fromDate,
toDate:toDate,
billTypeInd:billTypeInd,
dataElement:dataElement,
ediFileName:ediFileName,
ediBillName:ediBillName,
billId:billId,
claimantFirstName:claimantFirstName,
claimantLastName:claimantLastName,
insurerName:insurerName,
insurerFEIN:insurerFEIN,
insurerZip:insurerZip
}
})
.done(function(response) {
alert( "Result is: " + response);
});
This works without any problem from the get go. Now my question is how to bind the response to the backbone model?
Finally I figured out what was wrong. The call was inside a submit click handler, and $.ajax call or fetch is asynchronous. So by the time the call got reply from the server default action of submit click already took place (which is to reload the page). So by the time success or .done got called the whole page was reloaded. So I put event.preventDefault() at the beginning of handler method and let the handler receive the call back from the server and display it at the template. Thanks everyone for your time.

BackboneJS model.fetch() unsuccessful

Hi I have this model :
window.shop = Backbone.Model.extend({
initialize: function () {
console.log('initializing shop');
},
urlRoot: "shopData.json",
});
and then i go :
var myShop = new shop();
myShop.fetch({
success: function (model, resp){
console.log(resp);
},
error: function (model, resp){
console.log("error retrieving model");
}}, {wait: true});
now I'm always getting the error message - never reaching success :-(
thanks for any help.
Edit 1:
As per your comment the server is sending the proper response but Backbone is still calling the error function. Add the following line at the beginning of the error callback:
error: function (model, resp){
console.log('error arguments: ', arguments);
console.log("error retrieving model");
}
The first line should print an array of objects. The first element in the array should the jqXhr object, the second should be a string representation of the error. If you click on the first object, the dev tools will let you inspect its properties. Read up on the properties of the object here http://api.jquery.com/jQuery.ajax/#jqXHR.
Using that information you can verify if the jQuery is receiving an error from the server.
If there is no server side error, then check the value of the responseText property. That holds the string data returned from the server. $.ajax will try to parse that data into JSON. Most likely the parsing is throwing an error and the error handler is being raised instead.
Copy the response text and paste it into http://jsonlint.com/. Verify that the response sent from the server is valid JSON. Do update your question with the output of the console.log statement and the responseText property of the jqxhr object.
-x-x-x-
You seem to be using the model independently. As the per the documentation, http://backbonejs.org/#Model-url,
Generates URLs of the form: "/[urlRoot]/id"
That means, you are making a request to shopData.json/id. Also, you haven't specified the id.
Insert a console.log(myShop.url()) before the myShop.fetch(). Let us know whats the output. Also, possibly share the details of the ajax request as seen in Firebug or Chrome Dev Tools. I am interested in two things, the request url and the response returned by the server. (http://getfirebug.com/network)

Backbone.js DELETE request not firing

I'm trying to get the backbone.js DELETE request to fire, but don't see any requests being made in my console.
I have collection model like so:
var Model = Backbone.Model.extend(
{
urlRoot: '/test',
defaults:{}
});
var TableList = Backbone.Collection.extend(
{
url: '/test',
model: Model
});
In my view I'm running this:
this.model.destroy();
Everything seems to be running fine, I can see output coming from the remove function that calls the destroy so I know it's getting there plus it also successfully runs an unrender method that I have. Can't see any requests being made to the sever though?
If I am not mistaken, you have to have an id property on your model to ensure that it hits the correct url. IE if your model was...
var Model = Backbone.Model.extend({
url: '/some/url'
});
var model = new Model({
id: 1
});
model.destroy(); // I THINK it will now try and DELETE to /some/url/1
Without an id it doesn't know how to build the url correctly, typically you'd fetch the model, or create a new one and save it, then you'd have a Url...
See if that helps!
I found the issue to my problem, thought not a solution yet. I'm not sure this is a bug with backbone or not, but I'm using ajaxSetup and ajaxPrefilter. I tried commenting it out and it worked. I narrowed it down to the ajaxSetup method and the specifically the use of the data parameter to preset some values.
Have you tried using success and error callbacks?
this.model.destroy({
success : _.bind(function(model, response) {
...some code
}, this),
error : _.bind(function(model, response) {
...some code
}, this);
});
Might be instructive if you're not seeing a DELETE request.

Error callback always fired, even when it is successful

There should be a glitch in my syntax, or something I haven't understood, but when I am doing a save method on my model. The error callback is called whatever the outcome of the method.
#new_activity = new Activity()
#new_activity.save
know: $('input#know').val()
learn: $('input#learn').val()
success: -> console.log 'success'
error: -> console.log 'error'
In my case, since I do not really know whether the new_activity has effectively passed the validation, I have to do an ugly trick to add the activity to the collection. (By the way, I do not use the create method since I do want to have the different errors, and not a simple "false".
if #new_activity.has('know') and #new_activity.has('learn')
app.collections.activities.add #new_activity
When it is successful though; there is an alert of the created model.
Edit: Further details.
Here is my model:
initialize: ->
_.bindAll #, 'validate', 'errorHandler'
#.bind 'error', #errorHandler
validate: (attrs) ->
errors = []
# We only support a certain number of languages, we enforce that the user does not select a wrong set.
if _.isEmpty(_.intersection([attrs.know], ['en', 'fr'])) is true
errors.push 'This language is not currently supported.'
if _.isEmpty(_.intersection([attrs.learn], ['en', 'fr', 'de', 'es', 'zh', 'pt', 'ar', 'ja', 'ru'])) is true
errors.push 'You cannot learn this language yet.'
if _.isEmpty(errors) is false
errors
errorHandler: (model, error) ->
console.log error
When the validation occurs, and if the validate method returns nothing, it still triggers the error event, and the error variable contains the model (but no error message).
You should check whether the new_activity is saved properly, please verify that the server returns success response to the PUT request.
Furthermore, I have had issues with using Rails 3.1 standard format.json { head :ok } because it returns a single space as a reponse and application/json as content type. Backbone then tries to parse JSON and dies with an error.
The problem is the single space that Rails sends back with head :ok. If you send back an empty string, Backbone handles it fine.
The proper way to do that is to send back a 204 No Content. You can do that by replacing head :ok with head :no_content in the format.json block. Rails will not send back anything in the HTTP body.
I'm not sure what the cause of your error is, but I think I can help you pin it down:
Looking at the annotated source for Backbone.js, you can see that save() defers to sync(), which in turn defers to jQuery's $.ajax. So ultimately, your error function (wrapped by Backbone's wrapError) is called from that.
Unfortunately, the wrapper discards all but the jqXHR argument, making debugging a bit tricky. So you might want to try hacking your local Backbone.js source file to replace the existing wrapErrorfunction with something like this:
var wrapError = function(onError, model, options) {
return function(jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
console.log(textStatus);
console.log(errorThrown);
if (onError) {
onError(model, jqXHR, options);
} else {
model.trigger('error', model, jqXHR, options);
}
};
};
Then, at least, you'll see all of the debugging data provided by jQuery on your console.

Resources