I have this code:
app.Collections.quotes = new app.Collections.Quotes();
app.Collections.quotes.fetch({
success: function(){
console.log(app.Collections.quotes.at(0).get("NetAmount"));
}
});
Console.log returns 'undefined'.
Yet, I can see the returned response from the server is an array of Objects and Backbone does actually create 27 models, but none of them have any attributes!
Any ideas?
As per question comments, it looks like you may have overridden Model.parse. If you do, you need to return the attributes hash you want to set as the model's attributes:
parse: function(response) {
//do something with response
return response;
}
Related
I want to build a directive that checks for duplicate username. So I have created an index.html file and an uniqueId directive. Now in the directive I am not able to do ngModel.setValidity(). It is getting undefined.
Also I am fetching data from a local json file username.json.
When I console log console.log(ngModel.$setValidity('unique', unique)) I get undefined.
I have created a plunk for the code::
https://embed.plnkr.co/XTPf9PjiMn9if5Y0DaHt/
You need to iterate through the users present in JSON. And, if your currentValue matches any of those, you need to set it as invalid using $setValidity. Like this:
dataService.getUsers().then(function(currentusers) {
console.log(currentusers)
//Ensure value that being checked hasn't changed
//since the Ajax call was made
if (currentValue == element.val()) {
currentusers.forEach(function(user) {
if (currentValue === user.property) {
ngModel.$setValidity('unique', false)
}
});
}
}, function() {
//Probably want a more robust way to handle an error
//For this demo we'll set unique to true though
ngModel.$setValidity('unique', true);
});
});
Also, your service was getting the JSON every time. Alternatively, you can store your JSON response in a variable inside your angular service (which is a singleton) so it's faster than before. Like this,
dataFactory.getUsers = function() {
var deferred = $q.defer()
if (angular.isDefined(savedResults)) {
deferred.resolve(savedResults.data);
return deferred.promise;
} else {
return $http.get(serviceBase).then(
function(results) {
savedResults = results
return results.data;
});
}
};
Here, we return a resolved promise if data is already available. It will get the JSON for the first time and will use from within.
working plunker
please check plnkr link
If you type nitesh#gmail.com, it will display email already in use.
If you type nitesh#gmail.com1, it won't show error message.
I have changed condition.
I have a method in my angular 1.5 controller, as shown below but I wanted to refactor the ajax call into the factory itself but I'm having problems with promises.. I'm trying to get to a point where in my controller I can just call the method like I've shown below. Is this possible? I'm trying to avoid having the ...success(function(...) in the controller code.
Any help much appreciated.
Trying to move to
vm.member = someFactory.getMember(vm.id);
Existing working controller code
vm.myMethod = myMethod;
...
function myMethod() {
someFactory.getMember(vm.id).success(function(response) {
vm.member = response;
});
}
When I move the getMethod line into the factory the response is populated obviously but as soon as I come back to the controller, even with the return value from the factory being the response the result is undefined. I know this is because of promises but is there a design pattern I'm missing or a clean way of doing this. Using my currently approach my controller is littered with .success(function()...)
Many thanks!
The procedure is called promise unwrapping.
Besides the fact that success is deprecated and should be replaced with then,
someFactory.getMember(vm.id).then(function(response) {
var data = res.data;
...
});
it is totally ok to have this in controller.
The alternative to this pattern is to return self-filling object (something that ngResource $resource does):
function getMember(...) {
var data = {};
$http(...).then(function (response) {
// considering that response data is JSON object,
// it can replace existing data object
angular.copy(data, response.data);
});
return data;
}
In this case controller can get a reference to the object instantly, and the bindings of object properties {{ vm.member.someProperty }} will be updated in view on response.
The pattern is limited to objects (and arrays), scalar values should be wrapped with objects.
If I have a resource, e.g.
var resource = Restangular.all('things');
and I have json object that I want to post to the API
jsonObj = {
someVar: "x",
anotherVar: "y"
}
I can simply do
resource.post(jsonObj).then( ...etc... )
Now if I update the model on the clientside and want to save the changes, why can I not do:
resource.put(thingId, updatedJsonObj)
I'm having trouble getting my head around the demos around on the internet, as they all appear to need to do a get request before they can do a put? Which seems odd. It's worth mentioning that I am using Restangular in a SERVICE, not in a controller or directive. My service has a variable allMyThings which is the result of resource.getList() and I use that in various places in the application
Actually, if you take one item in the collection returned by getList(), you can use .save() on it, and it will call PUT method.
angular.module('demo').controller('DemoCtrl', function (myList) {
// myList is populated by Restangular.all('...').getList();
var item = myList[0];
item.name = 'foo';
item.save() // this one did a PUT :)
.then(function (res) {
// ...
});
});
See it in the docs.
NOTE :
Restangular will use the id property as id for PUT, DELETE, etc. calls.
If you want to change that behaviour, use this in module config :
RestangularProvider.setRestangularFields({
id: "_id"
});
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.