Issues with single-requests in Restangular - angularjs

I'm having a slight issue with my ability to consume REST data retrieved via Restangular in an angular controller. I have the following code which works fine for a list of accounts:
var baseAccounts = Restangular.all('accounts');
baseAccounts.getList().then(function(accounts) {
$scope.accounts = accounts;
});
This works perfectly for a list. I use similar syntax for a single account:
var baseAccount = Restangular.one('accounts');
baseAccount.getList(GUID).then(function(returnedAccount) {
$scope.currentAccount = returnedAccount;
});
I am using ng-repeat as the handling directive for my first request. I am attempting to bind with {{ account.name }} tags for the single request, but it does not seem to display any data despite the request being made properly. GUID is the parameter I must pass in to retrieve the relevant record.
I have combed through Restangular docs and it seems to me like I am composing my request properly. Any insight would be greatly appreciated.
EDIT: I've tried all of the solutions listed here to no avail. It would seem Restangular is submitting the correctly structured request, but when it returns it through my controller it shows up as just a request for a list of accounts. When the response is logged, it shows the same response as would be expected for a list of accounts. I do not believe this is a scoping issue as I have encapsulated my request in a way that should work to mitigate that. So, there seems to be a disconnect between Request -> Restangular object/promise that populates the request -> data-binding to the request. Restangular alternates between returning the array of accounts or undefined.

Have you looked at:
https://github.com/mgonto/restangular#using-values-directly-in-templates
Since Angular 1.2, Promise unwrapping in templates has been disabled by default and will be deprecated soon.
Try:
$scope.accounts = baseAccounts.getList().$object;

try:
var baseAccount = Restangular.one('accounts', GUID);
baseAccount.get().then(function(returnedAccount) {
$scope.currentAccount = returnedAccount;
});
The problem here is that it's expecting an array to be returned. I'm assuming that you are expecting an account object. Thus we need to use the get function, intead of getList()

The one() function has a second argument that accepts an id e.g. .one('users', 1). You can take a use of it.
CODE
var baseAccount = Restangular.one('accounts', 1); //1 would be account id
baseAccount.getList('account').then(function(returnedAccount) {
$scope.currentAccount = returnedAccount;
});
OR
var baseAccount = Restangular.one('accounts', 1); //1 would be account id
baseAccount.all('account').getList().then(function(returnedAccount) {
$scope.currentAccount = returnedAccount;
});
For more info take look at github issue
Hope this could help you, Thanks.

Related

Nodejs not sending response to Angular?

I have a doozy that I can't figure out whats going on.
In Mongo, I do a document.find(), which returns an array of object/s - All good.
I'm then trying to send on two objects back to the Angular Controller, the document object/s and the length of the array of objects.
Code:
function loadConnections(req, res) {
getConnections(req.user)
.then(function(results){
console.log('here');
console.log(results);
console.log(results.length);
var returnObject = {}
returnObject.count = results.length;
//returnObject.results = results[0]; // PROBLEM LINE
res.status(200).send(returnObject);
});
}
Problem I'm facing. In this scenario, it returns an array with 1 object. The array looks like:
[{id: XXX, test: YYY, test1: ZZZ}]
These have been what I've tried and tested:
returnObject.results = results[0].id; // works
returnObject.results = results[0].test; // works
returnObject.results = results[0].test1; //works
returnObject.results = results[0]; // doesn't work
returnObject.results = results; //doesn't work
But if I try to pass the entire object or the entire array, it hits an issue and doesn't send the response to the controller.
Any thoughts?
If you are using express, try to do a
res.send(200, returnObject);
or
res.json(200, returnObject);
that should do the trick!
Personally I would just calculate the length of the array after it arrives in my Angular client, rather than on the server. However, you should be able to accomplish what you're trying to do by doing this:
var returnObject = {
'count': results.length,
'results': results
};
res.json(returnObject);
Here's the doc: http://expressjs.com/en/api.html#res.json
Also just for general troubleshooting, the first thing you want to do is figure out where the inconsistency is starting. Does the data look right on the server before you send the response? Does the data look right on the client when your API handler receives the response? (I'm assuming $resource, or maybe you're using $http). So add a line like this just before you send the response from the server, and then add a similar line just after you receive the response in the client:
console.log(JSON.stringify(returnObject, null, 2));
Turns out it was my lodash library. I was using _.pluck and somewhere along the way, it's stopped working. Had to update it to _.map.

Restangular getList() does not return array of list items

I try to use Restangular to handle calls to my restful API.
Here is my code:
var baseStories = Restangular.all('stories/all');
baseStories.getList().then(function (stories) {
console.log(stories);
})
The console.log shows the full restangularized array instead of an array of stories as I'd expect.
I use the RestangularProvider.addResponseInterceptor from the docs to unwrap the response data.
Has anyone an idea what I'm missing?
Edit:
Below is a screenshot of the console.log output from the code above. I see two stories (which is correct) and a bunch of Restangular methods. Is it possible to only get the stories?
Actually addResponseInterceptor must return restangularized element. It is written in the documentation:
https://github.com/mgonto/restangular#addresponseinterceptor
In order to get clean response you have to call plain() method on the response element:
var baseStories = Restangular.all('stories/all');
baseStories.getList().then(function (response) {
$scope.stories = response.plain();
})

ngResource new instance error when call $query

Let's say I have a $resource like:
var Collections = $resource("http://somedomain/collections/:action", {
action: "#action"
});
If I create a new instance
var myCollections = new Collections()
When I do
myCollections.$query();
I get this error:
TypeError: value.push is not a function
Now, the response is an array as expected and everything seems to be in order.
If I do
var myCollections = Collections.query();
it works
Any ideas why? What am I doing wrong?
If you're using $resource in that way, I do believe there is no such thing is a $query(), only query() with no dollar sign in front of it. There is a $save() which I think can get pretty confusing.
I wish the documentation was a bit better on this subject, but one way to see all your possible calls on that object is checking under the prototype for when you console.log myCollections. That, and searching examples on the web.

laravel angularjs update multiple rows

i have a sortable table and after successfully moving an item i want to update all the rows in the databasetable which are effected from sorting.
my problem is that i dont know what's the best way to update multiple rows in my database with eloquent and how to send the data correct with angularjs
in angularjs i did this
//creating the array which i want to send to the server
var update = [];
for (min; min <= max; min++){
...
var item = {"id": id, "position": position};
update.push(item);
...
}
//it doesn't work because its now a string ...
var promise = $http.put("/api/album/category/"+update);
//yeah i can read update in my controller in laraval, but i need the fakeid, because without
//i get an error back from laravel...
var promise = $http.put("/api/album/category/fakeid", update);
in laravel i have this, but is there an possibility to update the table with one call instead of looping
//my route
Route::resource('/api/album/category','CategoryController');
//controller
class CategoryController extends BaseController {
public function update()
{
$updates = Input::all();
for($i = 0; $i<count($updates); $i++){
Category::where('id','=', $updates[$i]["id"])
->update(array('position' => $updates[$i]["position"]));
}
}
}
and yes this works but i think there are better ways to solve the put request with the fakeid and the loop in my controller ;)
update
k routing is solved ;) i just added an extra route
//angularjs
var promise = $http.put("/api/album/category/positionUpdate", update);
//laravel
Route::put('/api/album/category/positionUpdate','CategoryController#positionUpdate');
Try post instead put.
var promise = $http.post("/api/album/category/fakeid", update);
PUT vs POST in REST
PUT implies putting a resource - completely replacing whatever is available at the given URL with a different thing. By definition, a PUT is idempotent. Do it as many times as you like, and the result is the same. x=5 is idempotent. You can PUT a resource whether it previously exists, or not (eg, to Create, or to Update)!
POST updates a resource, adds a subsidiary resource, or causes a change. A POST is not idempotent, in the way that x++ is not idempotent.
By this argument, PUT is for creating when you know the URL of the thing you will create. POST can be used to create when you know the URL of the "factory" or manager for the category of things you want to create.
so:
POST /expense-report
or:
PUT /expense-report/10929
I learned via using following
Laravel+Angular+Bootstrap https://github.com/silverbux/laravel-angular-admin
Laravel+Angular+Material https://github.com/jadjoubran/laravel5-angular-material-starter
Hope this help you understand how to utilize bootstrap & angular and speed up your develop by using starter. You will be able to understand how to pass API request to laravel and get callback response.

AngularJS Execute function after a Service request ends

I am using AngularJS Services in my application to retrieve data from the backend, and I would like to make a loading mask, so the loading mask will start just before sending the request. but how can I know when the request ends?
For example I defined my servive as:
angular.module('myServices', ['ngResource'])
.factory('Clients', function ($resource) {
return $resource('getclients');
})
.factory('ClientsDetails', function ($resource) {
return $resource('getclient/:cltId');
})
So I use them in my controller as:
$scope.list = Clients.query();
and
$scope.datails = ClientsDetails.get({
date:$scope.selectedId
});
So the question would be, how to know when the query and get requests ends?
Edit:
As a side note in this question I've been using using angularjs 1.0.7
In AngularJS 1.2 automatic unwrapping of promises is no longer supported unless you turn on a special feature for it (and no telling for how long that will be available).
So that means if you write a line like this:
$scope.someVariable = $http.get("some url");
When you try to use someVariable in your view code (for example, "{{ someVariable }}") it won't work anymore. Instead attach functions to the promise you get back from the get() function like dawuut showed and perform your scope assignment within the success function:
$http.get("some url").then(function successFunction(result) {
$scope.someVariable = result;
console.log(result);
});
I know you probably have your $http.get() wrapped inside of a service or factory of some sort, but you've probably been passing the promise you got from using $http out of the functions on that wrapper so this applies just the same there.
My old blog post on AngularJS promises is fairly popular, it's just not yet updated with the info that you can't do direct assignment of promises to $scope anymore and expect it to work well for you: http://johnmunsch.com/2013/07/17/angularjs-services-and-promises/
You can use promises to manage it, something like :
Clients.query().then(function (res) {
// Content loaded
console.log(res);
}, function (err) {
// Error
console.log(err);
});
Another way (much robust and 'best practice') is to make Angular intercepting your requests automatically by using interceptor (see doc here : http://docs.angularjs.org/api/ng.$http).
This can help too : Showing Spinner GIF during $http request in angular
As left in a comment by Pointy I solved my problem giving a second parameter to the get function as following:
$scope.datails = ClientsDetails.get({
date:$scope.selectedId
}, function(){
// do my stuff here
});

Resources