Bug - AngularJS Service with GET JSON file - angularjs

I am working on a simple sample AngularJS application that reads data from an external JSON data file. I have tried everything, and I cannot find why the application does not work. Any input would be most appreciated.
'filmCtrl' Control:
angular
.module('mediaApp')
.controller('filmCtrl', function(filmList) {
var vm = this;
vm.films = filmList.retrieveFilms();
});
'filmList' Service:
angular
.module('mediaApp')
.service('filmList', function($http) {
var vm = this;
vm.retrieveFilms = function() {
return $http
.get('films.json')
.then(function(response) {
return response.films;
});
};
return vm;
});
JSON:
{
"films":[
{
"title": "Reservoir Dogs",
"director": "Quentin Tarantino",
"year": "1992"
},
{
"title": "2001: A Space Odyssey",
"director": "Stanley Kubrick",
"year": "1967"
},
{
"title": "Memento",
"director": "Christopher Nolan",
"year": "2000"
},
{
"title": "Enter the Dragon",
"director": "Robert Clouse",
"year": "1973"
},
[etc]...
]
}
All of these files are saved in the same folder, and have been included in my HTML file. The JSON has been validated. Where have I gone wrong?

As per my comments you can create service like this -
mediaApp.service('filmList', ['$http',
function($http) {
var vm = this;
vm.retrieveFilms = function() {
return $http.get('data.json');
};
return vm;
}]);
In controller you can consume this service like -
mediaApp.controller('filmCtrl', function(filmList) {
var vm = this;
filmList.retrieveFilms().then(function(response) {
vm.films =response.data.films;
});
});
Working Plnkr - http://plnkr.co/edit/6RVlvdh8oG5WaiEHaPdM?p=preview
It will work in FF but for some browsers it will throw CORS error so better run it on a server.

In a then(response) the response object has these properties:
data – {string|Object} – The response body transformed with the transform functions.
status – {number} – HTTP status code of the response.
headers – {function([headerName])} – Header getter function.
config – {Object} – The configuration object that was used to generate the request.
statusText – {string} – HTTP status text of the response.
So this should be
return $http
.get('films.json')
.then(function(response) {
return response.data.films;
});
instead of
return $http
.get('films.json')
.then(function(response) {
return response.films;
});
See the official doc for more info.
If you're not running a webserver of any kind and just testing with file://films.json, then you're probably running into same-origin policy issues. See:
http://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy
Some error message could be useful.

Related

AngularJS POST http://localhost:8080/test/GetAllLocation 405 (Method Not Allowed)

I have to get JSON data from the below GET Service
http://localhost:8080/test/GetAllLocation
When I hit above URL into my browser this gives me JSON data.
But I am unable to get JSON data into my AngularJS application.
My controller code is give below
(function () {
angular
.module('app')
.controller('VisitorsController', [ 'myService', VisitorsController])
.factory("myService", ['$http', function($http) {
return {
getResponders: function(servicesUrl) {
return $http.get(servicesUrl).then(function(response) {
console.log(response.status);
return response.data;
}).catch(function(response) {
console.log(response.status);
return response.data;
});
}
};
return myService;
}]);
function VisitorsController(myService) {
var vm = this;
var servicesUrl = 'http://localhost:8080/test/GetAllLocation';
myService.getResponders(servicesUrl).then(function(data) {
console.log(data);
if(data==null) {
console.log(data);
} else {
console.log(data);
}
}).catch(function(response) {
console.log(response.status);
return response.data;
});
vm.visitorsChartData = [ {key: 'UP', y: 5264}, { key: 'Critical', y: 3872},{key: 'Warning', y: 1000} ];
vm.chartOptions = {
chart: {
type: 'pieChart',
height: 210,
donut: true,
x: function (d) { return d.key; },
y: function (d) { return d.y; },
valueFormat: (d3.format(".0f")),
color: ['rgb(0, 150, 136)', '#E75753','#fbbc05'],
showLabels: false,
showLegend: false,
title: 'Over 9K',
margin: { top: -10 }
}
};
}
})();
When I run this application this will give me below error
AngularJS POST http://localhost:8080/test/GetAllLocation 405 (Method Not Allowed)
XMLHttpRequest cannot load http://localhost:8080/test/GetAllLocation. No 'Access-Control-Allow-Origin' header is present on the requested resource.The response had HTTP status code 405.
Your issue is CORS. I would do some reading on CORS. In particular "No 'Access-Control-Allow-Origin' header is present on the requested resource" leads you to believe the issue is with the header.
The issue can also be the server not being properly configured for CORS, however on the angular side try setting options for $HTTP in your app settings, here is an example of mine for Django:
app.config(['$httpProvider',
function ($httpProvider) {
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}
This changes the header name which has the XSRF token, which already has a default (see the doc). The actual header name may need to changed, I'm not sure of your server side implementation. If you are using Django let me know, I have more data for Django config.
Here is a similar post
You are making API request to http://localhost:8080 but your client is running on different web server/port. Ideally, instead of allowing CORS, you should have your client running on the same server.
Your browser blocks the API requests if the application is making API requests to another server on account of security issues. However this can be allowed by setting 'Access-Control-Allow-Origin' header on your APIs.
Depending on the type of server running on http://localhost:8080, you need to set 'Access-Control-Allow-Origin' header on your APIs.
You can choose to allow specific domains or all domains(*) to get programmatic access to your APIs.

need to declare all the error messages globally in a property file

I need to declare all the error message like (401,200 etc....) in a property file, need to access them later where ever its required
in the below format mostly
key=messsage
404 = This request caon't be processed
200 = your request is successfull
Is it posssible in angular ifso could any body give me an idea, thank u
======================================================================
I think ... it is possible. lol !
You can declare global value via JSON file. (keep it on your server)
See the JSON format here.
Example:
globalvalue.json
[
{
"key": 404,
"message": "This request caon't be processed"
},
{
"key": 200,
"message": "your request is successfull"
}
]
And next you just read that global value via your server it store the JSON file.
Angular Code:
angular
.module('app.services', [])
.factory('Friend', function ($http) {
return {
get: function () {
return $http.get('/globalvalue.json');
}
};
});
Then use your factory this way:
.angular
.module('app.controllers', ['app.services'])
.controller('yourCtrl', function ($scope, Friend) {
Friend.get().then(function (msg) {
$scope.msg = msg;
});
});
Cr. Reading data from JSON file in Angularjs.
let's fun. :)

Angular return promise from httpBackend.when()

How do you return a promise from httpBackend.when()? I wanted to load some canned data stored in a .json file and return that from httpBackend.whenGET(). When I try to return the promise from http.get('mydata.json') the response is returned to the failure callback of the factory.
function getAvailablePackagesComplete(response) {
return response.data;
}
function getAvailablePackagesFailed(error) { // {error = Object {data: undefined, status: 0, config: Object, statusText: ""}
$log.error(error.data.description);
return false;
}
function getAvailablePackages() {
return $http.get('/1.0/get-available-packages')
.then(getAvailablePackagesComplete)
.catch(getAvailablePackagesFailed)
}
var data = {"package": "test", "version": "1"}
$httpBackend.whenGET('/1.0/get-available-packages').respond(function(method, url, data) {
// return [200,data, {}] // this works
return $http.get('app/home/fixtures/mydata.json'); // contains {"package: "test", "version": "1"}
}); //this doesn't work
As it is currently, $httpBackend (from ngMockE2E) does not support promises within its .respond - See AngularJS GitHub Issue #11245. As $httpBackend should be used to avoid making real HTTP requests, but you could let some requests pass through.
From AngularJS Docs:
This implementation can be used to respond with static or dynamic responses via the when api and its shortcuts (whenGET, whenPOST, etc) and optionally pass through requests to the real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch templates from a webserver).
To work around what you're trying to do though, you could try to have getAvailablePackages() return the HTTP GET for your json file path and defining an $httpBackend.whenGET('pathTo.json').passThrough();
I was hitting the same issue and my use case was building a mock of my entire API in JS so that other people could work off line and develop the UI.
To achieve that I have developed a plugin called angular-mocks-async which decorates the httpBackend and adds the .whenAsync( ) APi to it. Than you can easily mock responses and return promises like so:
var app = ng.module( 'mockApp', [
'ngMockE2E',
'ngMockE2EAsync'
]);
app.run( [ '$httpBackend', '$q', function( $httpBackend, $q ) {
$httpBackend.whenAsync(
'GET',
new RegExp( 'http://api.example.com/user/.+$' )
).respond( function( method, url, data, config ) {
var re = /.*\/user\/(\w+)/;
var userId = parseInt(url.replace(re, '$1'), 10);
var response = $q.defer();
setTimeout( function() {
var data = {
userId: userId
};
response.resolve( [ 200, "mock response", data ] );
}, 1000 );
return response.promise;
});
}]);
You can return promises from http interceptors. Here is an example of delaying an HTTP call for 1 second. You can add this in your app.config(....)
$httpProvider.interceptors.push(function($q, $timeout) {
return {
'response': function(response) {
var defer = $q.defer();
$timeout(function() {
defer.resolve(response);
}, 1000);
return defer.promise;
}
};
});

unable to display the http get response from the factory in controller in Angularjs application

In my service I making http get request as shown below:
.factory('InvoicesGeneralService', function ($http) {
return {
getAgreementsByCourierId: function (courierId) {
console.log("Courier in Services" + courierId);
return $http.get('/api/agreements/byCourierId', {params: {courierId: courierId}}).then(function (response) {
return response;
});
}
};
});
And in browser console I am seeing the following response :
[
{
"id":3,
"number":"AGR53786",
"ediNumber":"EDI7365",
"startDate":"2012-09-02",
"endDate":"2018-07-01",
"courier":{
"id":2,
"name":"FedEx",
"url":"www.fedex.com",
"isActive":true,
"isParcel":true
},
"client":{
"id":4,
"code":"KJGTR",
"name":"Hearty",
"isActive":true,
"engageDate":"2011-07-07",
"isSendRemittance":true,
"upsUserName":"Tkd",
"upsPassword":"kuu",
"isEligibleForTracking":true,
"isEligibleForAuditing":true,
"status":5
}
}
]
And in my controller I am assigning it to result List :
$scope.resultList = InvoicesGeneralService.getAgreementsByCourierId(selCourierId);
But my resultList is always appearing as Empty. Can any one help me, why it is happening?
When I am trying to display resultList as shown below, it always shows empty object, {}. It supposed to display the response json array from the service but it is showing empty object.
<pre class="code"> {{resultList | json}}</pre>
$http returns a promise. Anything consuming that data needs to handle it like a promise too.
InvoicesGeneralService.getAgreementsByCourierId(selCourierId).then(function(data) {
$scope.resultList = data;
});
Also, your factory's then function is not doing anything at the moment. You should return the response's data from it.
return $http.get('/api/agreements/byCourierId', {params: {courierId: courierId}}).then(function (response) {
return response.data;
});

Module factory is not returning data

I am trying to read JSON reply from server. You can find my code here.
https://github.com/ameyjah/feeder
In firefox firebug, I can see that server has returned JSON reply but when I store that into $scope.variable, I am not able to access that information.
Module code
var res
angular.module('myApp.services', ['ngResource'])
.factory('feedFetcher', ['$resource',
function($resource) {
var actions = {
'sites': {method:'GET', params: { action:"sites"} ,isArray:false},
'feeds': {method:'GET', params: { action:"sites"} ,isArray:false}
}
res = $resource('/api/:action', {}, actions);
return res
}
]);
Controller code
$scope.sites = feedFetcher.sites().sites;
console.log($scope.sites);
Reply seen in firebug:
{
"sites": [
{
"id": 0,
"title": "google"
},
{
"id": 1,
"title": "yahoo"
}
]
}
I think I have messed up the way I should define my factory but I am not able to identify. Any help would be helpful.
When you call sites() it returns an empty object and initiates an AJAX request, which will populate the "sites" property on that object. I think you should use it like this:
$scope.results = feedFetcher.sites();
console.log($scope.results.sites); // will be undefined as AJAX not complete
Then in your html you can use the results and they will be filled in when AJAX completes, or watch for it:
$scope.$watch('results.sites', function() {
// this will be called twice, once initially
// and again whenever it is changed, aka when AJAX completes
console.log($scope.results.sites);
};

Resources