AngularJS Service for XHR - javascript

I am trying to create a service in AngularJS which would fetch me JSON data from a website.
I wrapped the service in a factory method as shown below
App.factory('httpService', function($http) {
delete $http.defaults.headers.common['X-Requested-With'];
return {
getData : function() {
var url = "http://www.reddit.com/.json?callback=JSON_CALLBACK";
return $http.jsonp(url).then(
function(result) {
return result;
});
}
}
});
The problem I'm coming across is that I receive an error Uncaught SyntaxError: Unexpected token :. When I use get() instead of json() I get a 501/CORS error.
The URLs from where I am trying to fetch the data are:
http://api.4chan.org/b/1.json
http://www.reddit.com/.json
following is a link to my jsfiddle with the rest of the code.
http://jsfiddle.net/fatgamer85/adPue/3/
Does any one has any idea on how to solve this?
EDIT: I have managed to get the data and solved the issue. Thanks to sza
Following is the code which I've used if anyone's interested
var myApp = angular.module("client", []);
myApp.factory('myXHRService', function($http) {
delete $http.defaults.headers.common['X-Requested-With'];
return {
getData : function(url) {
return $http.jsonp(url).then(
function(result) {
return result.data;
}
);
}
}
});
myApp.controller('MainCtrl', function($scope, myXHRService) {
$scope.xhrData = {};
$scope.data = {};
$scope.url = "http://www.reddit.com/.json?jsonp=JSON_CALLBACK";
myXHRService.getData($scope.url).then(function(data) {
var xhrData = angular.fromJson(data);
$scope.xhrData = xhrData.data.children;
});
});
myApp.config(function($httpProvider){
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
});
The main difference here is the callback in URL parameters jsonp apart from that, everything works fine and dandy.

I think it may relate to API endpoint issue of Reddit.com. If you try this API, it will work using jsonp
var url = "http://www.reddit.com/top.json?jsonp=JSON_CALLBACK";
For the API /.json, I suggest you implement the server side code to retrieve data though it returns valid JSON but somehow can't be accessed correctly across domain.

Related

angularjs: passing a service into another service?

I am trying to sort out the best way to do the following:
At the request of our backend developer we want to have a json file that contains a master list of the api urls that are used in requests by my frontend. This way the end user's browser only makes one request for the object and we can then pass them this into other services. so for example...
the dataUrl JSON contains the following
{
"emails":"json/emails.json",
"mapping":"json/mapping.json",
"profile":"json/profile.json"
}
and I would need to store that as a variable that could be used in all of my api calls like such:
app.factory('Emails', ['$http', function($http, Urls) {
var url = ""; //something here to get the dataUrl object for "emails"
var query = {};
query.getItems = function () {
return $http.get(url.emails); //from var emails above?
};
return query;
}]);
What is going to be my best approach to this?
This is what I tried so far and it didn't work...
app.factory('Urls', ['$http', function($http) {
var query = {};
query.getItems = function () {
return $http.get('json/dataUrls.json');
};
return query;
}]);
app.factory('Emails', ['$http', function($http, Urls) {
Urls.getItems().then(function(response) {
var url = response.data.emails;
console.log(url);
})
var query = {};
query.getItems = function () {
return $http.get('json/emails.json');
};
return query;
}]);
This results in a console error TypeError: Cannot read property 'getItems' of undefined
You are injecting dependency in wrong way
First inject it then create it's instance
Try this
Replace
app.factory('Emails', ['$http', function($http, Urls) {
to
app.factory('Emails', ['$http', 'Urls', function($http, Urls) {

AngularJs http request concats my data into a JSON key

Sometimes a behavior is so bizarre that I don't even know how to begin to google it. I'm fairly new at Angular, and I am trying to send POST data to my node server from the client. Here is the controller on the client side:
var app = angular.module("groomer", []);
app.controller("gCtrl", function($scope, $http) {
$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
$scope.send = function() {
$http({
method : "POST",
url : "/gUpdate",
data: {
gName:$scope.gName,
gPhone:$scope.gPhone,
gWebsite:$scope.gWebsite,
gEmail:$scope.gEmail,
gCustAcct:$scope.gCustAcct,
gAddress:$scope.gAddress,
gNotes:$scope.gNotes
}
}).then(function success(response) {
alert(console.log('Success!'));
}, function error(response) {
alert(console.log('Booooooo'));
});
};
});
What I naively imagine ought to show up at the server is:
req.body = {
gName:'a',
gPhone:'b',
gWebsite:'c',
gEmail:'d',
gCustAcct:'e',
gAddress:'f',
gNotes:'g'
}
But things get weird. What actually shows up at the server as the request body is:
{"{\"gName\":\"a\",\"gPhone\":\"b\",\"gWebsite\":\"c\",\"gEmail\":\"d\",\"gCustAcct\":\"e\",\"gAddress\":\"f\",\"gNotes\":\"g\"}":""}
In case it takes you a second to see what's happening here, that's all of my JSON keys and data in an object, double-quoted, escaped, concatenated as a string, and passed to the server inside an object as a JSON key corresponding to an empty value.
//so
var lifeMakesSense = {gName:'a',gPhone:'b',gWebsite:'c',gEmail:'d',gCustAcct:'e',gAddress:'f',gNotes:'g'}
//becomes
var waitNo = "{\"gName\":\"a\",\"gPhone\":\"b\",\"gWebsite\":\"c\",\"gEmail\":\"d\",\"gCustAcct\":\"e\",\"gAddress\":\"f\",\"gNotes\":\"g\"}"
//then
var whatEven = {waitNo:""} // nailed it
Thoughts?

Read JSON data in Angular JS script and use that data further in JS only

I have searched it a lot , in all cases , they usually want to show it on HTML directly , but my purpose is to use the data in Angular JS only.
angular.module('myApp').factory('UserService', ['$http', '$q', function($http, $q){
var url ;
$http.get('/HomeAccessService-1/static/js/data.json').then(function(response) {
url = response.data;
//alert(JSON.stringify(url.data));
});
//var REST_SERVICE_URI = 'http://localhost:8080/HomeAccessService-1/user/';
var REST_SERVICE_URI = JSON.stringify(url.data);
var factory = {
fetchAllUsers: fetchAllUsers,
createUser: createUser,
updateUser:updateUser,
deleteUser:deleteUser
};
return factory;
function fetchAllUsers() {
var deferred = $q.defer();
$http.get(REST_SERVICE_URI)
.then(
function (response) {
deferred.resolve(response.data);
},
function(errResponse){
console.error('Error while fetching Users');
deferred.reject(errResponse);
}
);
return deferred.promise;
}
I want to use this url data in other methods , the data is actually a REST API URL which i put in data.json file
{"data":"http://someotherip:8080/Service/user/"}
It shows object Object when alert ,
I dont want to show it in HTML but to use the data in angular js methods.
Alert is showing up before your response reach. Put alert inside request promise. You will get the response.
and use json.stringify(response.data) to make a json string
You should call the alert inside the promise otherwise it will be undefined when you alert it,
$http.get('/Service-1/static/js/data.json').then(function(response) {
url = response.data;
alert(JSON.stringify(url.data));
});*/
Inorder to display the correct data, you should use JSON.stringify()
alert(JSON.stringify(url.data));
You can do one of the two things
1. Add REST_SERVICE_URI = .. instead of that alert statement OR
2. Add those geturl call inside fetchAllUsers function and then do your next steps once you get resopnse.data
//// Add url part inside get response
var url;
var REST_SERVICE_URI;
$http.get('/HomeAccessService-1/static/js/data.json').then(function(response) {
url = response.data;
REST_SERVICE_URI = JSON.stringify(url.data);
});
...
//// OR do it in sync
function fetchAllUsers() {
var deferred = $q.defer();
$http.get('/HomeAccessService-1/static/js/data.json').then(function(response) {
url = response.data;
REST_SERVICE_URI = JSON.stringify(url.data);
$http.get(REST_SERVICE_URI)
.then(
function (response) {
deferred.resolve(response.data);
},
function(errResponse){
console.error('Error while fetching Users');
deferred.reject(errResponse);
}
);
});
return deferred.promise;
}
$scope.jsondata=json.stringify(response.data)
console.log(jsondata.url);
take all the json in one javascript variable then travarse that using loop or variable like jsondata.url and use it in ur future api call.

Angularjs Flickr API SyntaxError: Unexpected token when using nojsoncallback=1

I have an angularjs app to call a flickr api.
I want the data in RAW json format with no function wrapper and as per the docs, applying &nojsoncallback=1 .
However I'm getting the following console error. SyntaxError: Unexpected token '
This error only appears when applying &nojsoncallback=1 to the url. However I want RAW json with no wrapper.
If I don't apply the above to the url and simple use https://api.flickr.com/services/feeds/photos_public.gne?tags=trees&format=json I get no error, but when console logging out the typeof I get 'string' displayed.
I then try parsing this into JSON and get another error because it has a wrapped. Hence why I want RAW.
Below is the code I have so far. Any help - much appreciated.
JS
(function(){
'use strict';
var app = angular.module('flickrApp', []);
app.controller('FlickrFeedController', ['$http', '$scope', function($http, $scope){
// grab the flickr api
var response = $http.get('http://crossorigin.me/https://api.flickr.com/services/feeds/photos_public.gne?tags=trees&format=json&nojsoncallback=1');
// on success
response.success(function(data){
// console logging out the typeof gives 'string'
console.log(typeof(data));
// since it's a string I would then want to convert it into a json object
// but I need to sort the current error out first
// data = JSON.parse(data);
// console.log(typeof(data));
});
}]);
})();
EDIT:
This is a work around removing &nojsoncallback=1 from the url (removing the console error) and since the data comes back as a string having to replace characters, then parse. Not great but I get the required output (object) and thought I'd add it up here for others to view.
JS
(function(){
'use strict';
var app = angular.module('flickrApp', []);
app.controller('FlickrFeedController', ['$http', '$scope', function($http, $scope){
// grab the flickr api
var response = $http.get('http://crossorigin.me/https://api.flickr.com/services/feeds/photos_public.gne?tags=trees&format=json');
// on success
response.success(function(data){
// typeOf is 'string' even though format=json is specified in the url
//console.log(typeof(data));
//console.log(data);
// work-around since data is returned as a string
data = data.replace('jsonFlickrFeed(', '');
data = data.replace('})', '}');
data = data.replace(/\\'/g, "'");
// parse the data
data = JSON.parse(data);
// typeOf is 'object'
console.log(data.items);
console.log(typeof(data));
});
}]);
})();
Generate angular resource to call the api with format: {'json', jsoncallback: 'JSON_CALLBACK'}. Check complete solution here - http://plnkr.co/edit/Lxxkb9?p=preview
var app = angular.module('flickrApp', ['ngResource']);
app.factory('Flickr', function($resource, $q) {
var photosPublic = $resource('http://crossorigin.me/https://api.flickr.com/services/feeds/photos_public.gne?tags=trees&format=json',
{ format: 'json', jsoncallback: 'JSON_CALLBACK' },
{ 'load': { 'method': 'JSONP' } });
return {
get: function() {
var q = $q.defer();
photosPublic.load(function(resp) {
q.resolve(resp);
console.log(resp.items);
})
return q.promise;
}
}
});
app.controller('FlickrCtrl', function($scope, Flickr) {
Flickr.get();
});

Wrap angular $resource requests not returning POST data

I'm working on wrapping my $resource requests in a simple wrapper. The main idea
is to be able to add some logic before the request is made. I've followed the nice article written by Nils.
Here you can see a service definition to access the REST API module.
resources.factory('Device', ['RequestWrapper', '$resource', 'lelylan.config', function(RequestWrapper, $http, config) {
var resource = $resource(config.endpoint + '/devices/:id', { id: '#id' });
return RequestWrapper.wrap(resource, ['get', 'query', 'save', 'delete']);
}]);
And here you can see the request wrapper definition.
resources.factory('RequestWrapper', ['AccessToken', function(AccessToken) {
var requestWrapper = {};
var token;
requestWrapper.wrap = function(resource, actions) {
token = AccessToken.initialize();
var wrappedResource = resource;
for (var i=0; i < actions.length; i++) { request(wrappedResource, actions[i]); };
return wrappedResource;
};
var request = function(resource, action) {
resource['_' + action] = resource[action];
resource[action] = function(param, data, success, error) {
(AccessToken.get().access_token) ? setAuthorizationHeader() : deleteAuthorizationHeader()
return resource['_' + action](param, data, success, error);
};
};
var setAuthorizationHeader = function() {
$http.defaults.headers.common['Authorization'] = 'Bearer ' + token.access_token;
};
var deleteAuthorizationHeader = function() {
delete $http.defaults.headers.common['Authorization']
};
return requestWrapper;
}]);
Everything works just fine for the GET and DELETE methods (the ones that does not returns
a body seems), but I can't get $save working. What happens is that when the JSON of the
created resources returns it is not added. I have only the data I've set on the creation
phase. Let me make an example.
In this case we use the wrapped resource. If I try to get the #updated_at attribute I can't
see it. In the Chrome inspector I can see how the resource is successfully created.
$scope.device = new Device({ name: 'Angular light', type: 'http://localhost:9000/types/50bf5af4d033a95486000002' });
$scope.device.$save(function(){ console.log('Device Wrapped', $scope.device.created_at) });
# => undefined
If I use $resource everything works fine.
// Suppose authorization is already set
var Resource = $resource('http://localhost\\:9000/devices/:id');
$scope.resource = new Resource({ name: 'Angular light', type: 'http://localhost:9000/types/50bf5af4d033a95486000002' });
$scope.resource.$save(function(){ console.log('Device Base', $scope.resource.created_at); });
# => 2013-02-09T12:26:01Z
I started to check the angular-resource.js code but after few hours I couldn't really figure
it out. I can't get why the body is returned, but in the wrapper resource it is not accessible.
Any idea or help would be appreciated. Thanks.
While diving into AngularJS source code I've found the solution.
The problem was that the wrapper was returning a function instead of an object and this was giving some problems. The solution is to change the following row in the Wrapper:
return resource['_' + action](param, data, success, error);
with this one:
return resource['_' + action].call(this, params, data, success, error);
Why? The fast answer is because in the source code of angular-resource they use it. Actually #call run the function sending this to the calling object. It is often used to initialize an object. Learn more here.

Categories

Resources