I am having problems figuring out the model.save syntax in Backbone + Coffeescript. (Rails 3)
I have the following:
#options.product_search.save({'url' : $("#product_search").val()},
{success: (event) => alert "StackOverflow"},
{error: (response) => alert "oh no!"}
)
The success-event works in this case, the error-event doesn't.
I also can't figure out how to add multiple actions to a success-event as coffeescript gives me a syntax-error when I split the code into multiple lines inside the success event.
Thank you for your help!
Best, Phil
You're putting in a third parameter into the save method, where it only takes two:
model.save([attributes], [options])
This is just a coffeescript/javascript syntax error that's easy to fix.
Try this:
#options.product_search.save
url: $("#product_search").val()
,
success: (model, response) ->
alert "StackOverflow"
alert "More alerts"
error: (model, response) ->
alert "oh no!"
Related
Whilst attempting to run integration tests with Angular 2 and Karma test runner the following issue became clear. A test was always passing even when it should have been failing.
The issue occurs when the expect() method is placed inside the subscribe() method of an Observable.
The need to do this arose as the test would subscribe to the Observable and then continue processing the rest of the test before the Observable has finished executing.
However, placing the expect within the subscribe() method automatically causes the test to pass even when there are very obvious syntax errors:
it('should pass or fail', inject([Service], (_service : Service) => {
let result = _service.returnObservable();
result.subscribe((sfasdasdaa23231gr) => {
expect(r.isAfhahzdzd vailable).not.35q6w623tyrg /.0824568sfn toBe(truDDIDIDIDDIe);
});
}));
the previous code passes, but how? there are syntax errors everywhere. Does anyone know where this issue lies? In the testing or in the subscribe() method?
Because it's asynchronous processing, you should add the async method:
it('should pass or fail', async(inject([Service], (_service : Service) => {
let result = _service.returnObservable();
result.subscribe((sfasdasdaa23231gr) => {
expect(r.isAfhahzdzd vailable).not.35q6w623tyrg /.0824568sfn toBe(truDDIDIDIDDIe);
});
})));
This example is attempting to make synchronous code asynchronous. All examples I found were doing the opposite except the main first example at docs.angularjs.org .. $q below.
The doc lists a $q constructor which I am attempting to use. Unfortunately, the jsfiddle Angular libraries 1.1.1 and 1.2.1 provide a $q object (not a function) as in this example. Instead, I'll have to provide my example and hope that someone will see the bug.
https://docs.angularjs.org/api/ng/service/$q
I need to see "this does not happen!" line to execute.
f = function(name) {
return $q(function(resolve, reject) {
console.log "this does not happen!"
resolve('great')
});
}
f(name).then(function(result) {
console.log 'result', result
}, function(error) {
console.log 'error', error
});
Instead of logging "this does not happen!" followed by "great", I actually see the function passed to $q logged::
result function(resolve, reject) {
console.log "this does not happen!"
resolve('great')
}
Can someone see what I did wrong?
You are doing nothing wrong. I don't really think it's appropriate that the angular docs show that code with this line hidden right above it:
While the constructor-style use is supported, not all of the
supporting methods from ES6 Harmony promises are available yet.
It causes much confusion, as you an see.
Use the constructor method (like Zipper posted)
var dfd = $q.defer();
and then you can do the following:
dfd.reject('some value');
dfd.resolve('some value');
A little hard to see exactly what you're attempting, but here is some code we use that might help.
f = function(someValue){
var deferred = $q.defer();
doSomethingAsync(someValue, function(result){ return deferred.resolve(result)});
return deferred.promise;
}
f("foo").then(function() {alert("I was called after the async thing happened")})
I have a collection: conditions. In a view, after returning an HTTP 403 error response, I want to obviously NOT create the model:
var attributes = ...;
conditions.create(attributes, {
error: function (model, response) {
conditions.trigger('error');
var response = JSON.parse(response.responseText);
console.log(response);
}
});
The error callback is being called correctly. The response is logged correctly. But backbone still adds the (broken) model to the collection! When I look at conditions.toJSON(), there is a new model with some broken attributes.
I returned an error from the server, how do I insist that Backbone not add the new model to the collection?
I can do conditions.remove(model) in the callback, but should I have to?
You can pass {wait: true} to the create method.
Creating a model will cause an immediate "add" event to be triggered on the collection, as well as a "sync" event, once the model has been successfully created on the server. Pass {wait: true} if you'd like to wait for the server before adding the new model to the collection.
http://documentcloud.github.com/backbone/#Collection-create
var mdl = Backbone.Model.extend({
defaults:{
url:'/displayPostVariables.php',
age:0
},
initialize:function(opt){
this.url = function (){
return opt.url
}
}
})
mdli = new mdl({
'name' :'rajkamal'
})
jQuery.ajaxSetup({
'beforeSend': function(xhr) {
xhr.setRequestHeader("Accept", "text/html")
}
})
mdli.fetch({
success : successcallback,
error:errorcallback
});
Ajax call is going but, always ends up with the error callback.
Looks like this post model.fetch success callback does not fire on firefox, but works on chrome but there is no javascript code in that.
Thanks.
Try also passing dataType: 'json' to the fetch.
I had the same problem with fetch only ever returning my error callback.
In the end, it was because I had not specified an id in the object on the server like this:
{"title":"The Green Mile ","author":"Stephen King","img":"green_mile.jpg","id":2}
I think Backbone expects certain properties to be present in the JSON, though I was unable to find any documentation about this. The way I solved it was to do model.save() and to look at the object that was being saved.
For reference, I had the same issue because of an unsafe method incorrectly injecting NaN into the json response
{"progress":NaN}
which failed to be correctly parsed and forced the error callback
I had this issue, and it was due to using single quotes instead of double quotes to surround attributes and values in the API's JSON response.
Specify the url outside of defaults
= Backbone.Model.extend({
url : "/displayPostVariables.php",
defaults:{
},
validation: {
}
});
So, within one of my views, I've got this function:
delete_model: function() {
var answer = confirm("Are you sure you want to delete this element?");
if (answer) {
this.model.destroy({
success: function() {
console.log("delete was a success");
}
});
}
});
When I ping that, the Ajax call goes out, the backend properly deletes the model and returns a 200 header with "OK" as the body...but the success event never fires. Am I missing something? What should I have the backend serve to fire that event?
I just had the same problem. The solution that worked for me was to make sure I return a json model from the server that corresponds to the deleted one.
edit: returning an empty json response will suffice.
Did not work:
delete(model) {
// deleted model from db
return "Model was deleted";
}
This did work:
delete(model) {
// deleted model from db
return model;
}
or:
delete(id) {
// deleted model from db with this id
return new Model {id: id};
}
Had the same problem using Backbone 1.5.3 with Rails. I tried rudena's solution, and it works!
Here's what my controller's delete function looked like initially:
def destroy
#cell = current_user.cells.find(params[:id])
#cell.destroy
render :json => "success"
end
And here's what worked:
def destroy
#cell = current_user.cells.find(params[:id])
#cell.destroy
render :json => #cell
end
That looks good to me, exactly what I have everywhere (except I have function(model) but that shouldn't matter at all) I do know that older versions of backbone didn't use the destroy(options) but instead had destroy(success, failure). Can you make sure you have the latest version.
Had this problem come up with my UI as well. Upon DELETE, the API came back with an empty 200 response.
What's happening is, jQuery expects a json response body, but when the response comes back empty, json parsing fails and the error callback is triggered.
My solution was to override the Model's sync method:
var MyModel = Backbone.Model.extend({
// Fix for empty DELETE response
sync: function(method, model, options) {
if (method === 'delete') {
options.dataType = 'html';
}
Backbone.sync.call(this, method, model, options);
}
});
This works because options is passed to jQuery's ajax call and we're instructing jQuery not to expect json.