Restangular put requests.. how and why? - angularjs

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"
});

Related

how to return a value from a ajax promise

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.

Assigning prority in calling Restangular service

I am working with angularjs and Restangular. I want to assign some value to the object by calling some restangular service and after that updated object should be used for later purpose like in post code.
The code block is :
$scope.myObject={};
Restangular.one("getProperties").get().then(function(properties){
$scope.myObject.properties=properties;
});
var postData = Restangular.all('AnotherPostService');
postData.post($scope.myObject).then(function (returnedObject) {
});
}, function (error) {
});
First I want to call getProprties rest service, that should assign the values to $scope.myObject.properties object then updated $scope.myObject should be passed to post method AnotherPostService to make database related updation task.
My problem is that post method get called before assigning properties to object, how can I restrict/assign the priority of calling rest service, so that post method should be called on initializing the values?
Simply create a function and call it when your first call has returned, like so:
$scope.myObject = {};
Restangular.one("getProperties").get().then(function(properties){
$scope.myObject.properties = properties;
doSecondOperation();
});
function doSecondOperation() {
var postData = Restangular.all('AnotherPostService');
postData.post($scope.myObject).then(
function (returnedObject) {
},
function (error) {
}
);
};
Or if you don't need anything else to call it, simply put the actual code in the doSecondOperation method directly inside the success handler of the first operation, just after setting $scope.myObject.properties.
Also your braces were a little messed up... I think I fixed them... :)

Restangular PUT attaches _id two times for no reason

Iam using Restangular on the clientside with _id as Id field. Sadly Restangular generates wrong URLs, maybe you could say me where the error is?
Restangular.all('/users').one(id).get().then(functon(results) {
$scope.data = results;
})
After the user edited the data:
$scope.save = function() {
$scope.data.put().then(...);
};
This very simple sample generates the following URL with the id twice. I have no idea what went wrong. :(
PUT /users/537283783b17a7fab6e49f66/537283783b17a7fab6e49f66
Solved it by changing the Request workflow of Restangular.
I don't now why, but this approad does not work:
Restangular.all('/users').one(id).get() ... result.put();
But this does:
Restangular.one('/users/',id).get() ... result.put();
Also it is important to tell Restangular that you were using _id instead of id:
angular.module('App').config(function(RestangularProvider, AppSettings) {
RestangularProvider.setRestangularFields({id: "_id"});
});

AngularJS Service -> Controller population

All over my code I have things like:
SearchModel.findAll($scope.report).then(function (xhr) {
$scope.searchResults= xhr.data;
});
is there anyway to just automagically assign the searchResults variable to the view after the request is done. Seems like there should be if not...
Promises are only resolved during a $digest cycle, so this should "automagically" update.
It really is that easy!
To prove it I made a fiddle that simulates a server response using a service and assign the data to a scope. The dom will automatically display the data.
service.get().then(function(data) {
$scope.data = data;
});
Hope this helped!
If you are dealing with a promise that returns an array, you can use a helper function like this:
app.factory('PromiseList', function() {
return function(promise, error) {
var list = [];
promise.then(function (result) {
angular.copy(result, list); # or in your case .copy(result.data, list)
}, error);
return list;
}
});
Then in your code, do:
$scope.searchResults = PromiseList(SearchModel.findAll($scope.report))
You can also use this solution with other kinds of objects, however not with strings or numbers as they are immutable objects in JavaScript.
If you are only developing for an old version of AngularJS (think pre-1.2), you can also just pass the promise to the template and it will be unwrapped automatically.

How do I define Angular $resource to pass parameters correctly

I need to call a web service that requires a list of IDs in the form:
http://service_addr?itemID=34&itemID=36 ...
I tried setting up my service factory as:
.factory("doService", [$resource, function($resource) {
return $resource("service_addr", {}, {
'create' : {method:POST, isArray:true} }); }])
In my controller I invoke the service with this code:
var ids = [];
angular.forEach(listofIDs, function(anId) {
ids.push( { itemID : anID } );
}
doService.create(ids, {}, function (response) {
... do response stuff
}
in the console the POST return a 40 Bad request error. The request is malformed in the parameters as shown below:
http://service_addr?0=%5Bobject+Object%5D&1=%5Bobject+Object%5
How can I get the required parameters passed correctly?
Adding to ricick's answer, you could also pass the IDs in the format
http://service_addr?itemIDs=34,36,38
by doing
ids.join(',')
The issue is you can't have more than one parameter with the same name in GET, so even if angular could pass the data your server will only see one value (unless you're cheating and procssing the url string manually).
A better solution would be to something like:
http://service_addr?itemID0=34&itemID1=36itemID1=38&itemIDCount=3
that way you create a seperate parameter for each variable.

Resources