Restangular data, getting into $scope for a list - angularjs

Been wrestling with API stuff all day, and decided to use Restanglar. Really having issues getting the data out, and into $scope.
I understand that it won't just be the JSON that is returned from the API, and has a bunch of other internal methods etc. But when I get the data out, I can see it buried somewhere in the debugging with console.log, but I can't seem to get it into $scope to use it in my view which was working fine previously.
How can I get that data out into my $scope, and therefore my view?
Model
angular.module('horse', ['restangular'])
.config(function(RestangularProvider) {
RestangularProvider.setBaseUrl('http://url/api');
RestangularProvider.setResponseInterceptor(
function(data, operation, what) {
if (operation == 'getList') {
return data[what];
}
return data;
});
});
Controller
angular
.module('horse')
.controller("IndexController", function ($scope, Restangular) {
$scope.horse = null;
$scope.showSpinner = true;
Restangular.all('horse').getList().then(function(horse) {
$scope.horse = horse;
console.log($scope.horse);
});
});
API response
{"error":false,"horse":[{"id":"1","name":"horse 2"},{"id":"2","name":"horse 2"}]}
Edit 1
Restangular response
[Object, Object, route: "horse", getRestangularUrl: function, getRequestedUrl: function, addRestangularMethod: function, clone: function…]
Edit 2
I have also tried this - https://github.com/mgonto/restangular#using-values-directly-in-templates
$scope.horse = Restangular.all('horse').getList().$object;
Which just results in an empty array being output. I have also tried removing the setResponseInterceptor and modifying the structure of the api to result the data array directly without the meta stuff (error, etc), no joy :(

The data seems to be coming through. I notice you're using Steroids, have you checked the markup and not just the console?
Make sure you set the scope spinner to false, to ensure that the spinner is hidden when the data comes through.
$scope.ShowSpinner = false;

Assuming that what you have shown as "API response" is what's getting outputted from the console.log in your controller, it seems that all you need to do is set your scope model the the property "horse" in the response data like this:
$scope.horse = horse.horse;
Since that reads pretty oddly, you should change the param name of the .then callback to data, which would be a much more agnostic and standard param name. If you make that change you can set your horse data to your scope model from inside your callback like this:
$scope.horse = data.horse;
If I misunderstood your question let me know. Hope this is helpful.

Related

$http.then callback not being called

I have a $http.post call but the callback function does not get called. I have the exact same code for another call and that one works. Can you see any issues with the following code.
var data = {entityIds: $scope.allEntityIds, accountIds: $scope.accountIds};
$http.post("http://localhost:8080/psi4web/rest/social/posts", data,
{params: {filter: $scope.filters,
pageNum: $scope.pageNum, pageSize: $scope.pageSize}})
.then(function(res) {$log.info("test me")}, onError);
For debugging purposes, I added an inline function inside then() as shown above and that doesnt work either. I made sure that the data is being returned by the backend.
Thanks.
Just a few minor details that are keeping you from having success. Corrected code below.
var data = {entityIds: $scope.allEntityIds, accountIds: $scope.accountIds};
var myPost = $http.post("http://localhost:8080/psi4web/rest/social/posts", data, {params: {filter: $scope.filters, pageNum: $scope.pageNum, pageSize: $scope.pageSize}});
myPost.then(function(res){
$log.info("test me");
}, function(){
onError();
});
Figured it out. The issue was that I had one .jsp page load the other while this http call was being processed and that was wiping out the $scope in my .js script which was being shared by both the jsp pages. Basically, my structure of files and loading things wasn't right (being a newbie to angularjs)
You may have forgotten to inject the dependency on $q which is responsible for providing $promise

Understanding BackboneJS flow

I have been given a Project which is written entirely in Backbone.js, which I am supposed to change according to our specific needs. I have been studying Backbone.js for the past 2 weeks. I have changed the basic skeleton UI and a few of the features as needed. However I am trying to understand the flow of the code so that I can make further changes.
Specifically, I am trying to search some content on Youtube. I have a controller which uses a collection to specify the url and parse and return the response. The code is vast and I get lost where to look into after I get the response. I tried to look into views but it only has a div element set. Could someone help me to proceed. I wont be able to share the code here, but a general idea of where to look into might be useful.
Code Snippet
define([
'models/youtubeModelForSearch',
'coretv/config',
'libs/temp/pagedcollection',
'coretv/coretv'
],function( youtubeModelForSearch, Config, PagedCollection, CoreTV ) {
"use strict";
return PagedCollection.extend({
model: youtubeModelForSearch,
initialize: function() {
this.url = 'http://gdata.youtube.com/feeds/api/videos/?v=2&alt=json&max-results=20';
},
fetch: function(options) {
if (options === undefined) options = {};
if (options.data === undefined) options.data = {};
//options.data.cmdc = Config.getCMDCHost();
//CoreTV.applyAccessToken(options);
PagedCollection.prototype.fetch.call(this, options);
},
parse: function(response) {
var temp = response.feed
/*temp["total"] = 20;
temp["start"] = 0;
temp["count"] = 10; */
console.log(temp);
return temp.entry;
},
inputChangeFetch: function(query) {
this.resetAll();
if(query) {
this.options.data.q = query;
// this.options.data.region = Config.api.region;
//this.options.data.catalogueId = Config.api.catalogueId;
this.setPosition(0);
}
}
});
});
Let's assume your collection endpoint is correctly set and working. When you want to get the data from the server you can call .fetch() on you collection.
When you do this, it will trigger an request event. Your views or anybody else can listen to it to perform any action.
When the data arrives from the server, your parse function is called, it is set using set or reset, depending the options you passed along fetch(). This will trigger any event related to the set/reset (see the documentation). During set/reset, the data retrieved from your server will be parsed using parse (you can skip it, passing { parse: false }.
Right after that, if you passed any success callback to your fetch, it will be called with (collection, response, options) as parameters.
And, finally, it will trigger a sync event.
If your server does not respond, it will trigger an error event instead of all this.
Hope, I've helped.

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

How to populate Angular UI Bootstrap Typeahead with newest $resource

According to this Paweł Kozłowski's answer, Typeahead from AngularUI-Bootstrap should work when asynchronously obtaining popup items with $resource in newest Angular versions (I'm using 1.2.X).
Plunk - Paweł's version - Typeahead with $http
I guess I don't know how to use it properly (As a result I get an error in typeaheadHighlight directive's code - typeahead treats instantly returned Resources as strings and tires to highlight them).
Plunk - Typeahead with $resource
I think the critical code is:
$scope.cities = function(prefix) {
var p = dataProviderService.lookup({q: prefix}).$promise;
return p.then(function(response){
$log.info('Got it!');
return response.data;
});
return p;
};
I've tried bunch of stuff - returning $promise (version from Plunker), query(), then().
Currently, I'm using $http for this functionality in my app and I'm ok with it. Still, just wanted to know how to achieve the same with $resource.
You might want to take a look at this: https://github.com/angular/angular.js/commit/05772e15fbecfdc63d4977e2e8839d8b95d6a92d
is ui.bootstrap.typeahead compatible with those changes in $resource's promise API ?
Should be:
$scope.cities = function(prefix) {
return dataProviderService.lookup({q: prefix}).$promise.then(
function(response){
// might want to store them somewhere to process after selection..
// $scope.cities = response.data;
return response.data;
});
};
This is based of the angular commit mentioned above, and it worked for me on Angular 1.2.13
Thanks to the answer from #andrew-lank, I did mine with $resource as well. I didn't have a data attribute in my response though. I used the query method on $resource, which expects a responsetype of array so maybe that is why there is no data attribute. It is an array of Resource objects, each of which contains the data. So my code is slightly simpler, looks more like this:
$scope.cities = function(prefix) {
return dataProviderService.query({q: prefix}).$promise.then(
function(response){
return response;
});
};
I ran into this same problem and it had me banging my head against the wall. The problem is with the data service since it is returning an array of strings instead of wrapping them in a JSON object. $resource will not work with an array of strings.
For additional info, check out this answer:
One dimensional array of strings being parsed to 2d by angular resource
typeahead="i.t_UserName for i in employeeInfo | filter:$viewValue | limitTo:4"
goes as an attribute of your html input
and in your controller (using employee resource)
$scope.employeeInfo = getEmployeeResourceSvc.getEmplInfo.query(function(response){
$scope.employeeInfo= response;
});
In the ui-bootstrap 13.0 and angular 1.3, you can now do the following:
$scope.cities = function (q) {
return $scope.resource.query({ q: prefix }).$promise
}

AngularJS - Access JSON object associated to a model

I have a service that returns JSON, assume this is the response:
{
"model": 48870,
"id": 20
}
I can do this:
$scope.response = Service.get();
And it will assign the JSON response to $scope.response. The issue here is I cannot directly access model or id via $scope.response.model or $scope.response.id, respectively. My workaround for this situation is to define a function in the service's success callback and fetch model or id from data. But this is not very practical considering $scope.response contains the entire JSON object and should in theory (and the sake of clean code) let me access its children.
Two questions here:
Is it a limitation of AngularJS representation of models?
How can I point to children (even grandchildren) without having to define a success callback for each call?
Once the asynchronous HTTP call returns, it is safe to access response's properties directly.
See this short example
app.controller('MainCtrl', function($scope, $resource) {
$scope.data = $resource('data.json').get(function() {
$scope.loaded = true;
//now it's safe to access $scope.data's properties:
$scope.data.foo = $scope.data.id + ':' + $scope.data.model;
});
});
UI bindings will work automatically.
I think what you are looking for is described here:
http://docs.angularjs.org/tutorial/step_05

Resources