$http.get 404 of JSON file using .then - angularjs

I was running through a set of Angular videos on YouTube and found out that .success is deprecated, and to use .then instead. I get a 404 error using both a .json file and a .txt file. I tried using .txt as people mentioned browsers don't allow local files to access other local files.
This is the $http request I have at the moment
$http.get('data/ninjas.txt').then(function(response) {
// Success!!!
$scope.ninjas = response.data;
});
This is my .json file which is valid through JSONLint
[{
"name": "Yoshi",
"belt": "green",
"rate": 50,
"available": true,
"thumb": "content/img/yoshi.png"
}, {
"name": "Crystal",
"belt": "yellow",
"rate": 30,
"available": true,
"thumb": "content/img/crystal.png"
}, {
"name": "Ryu",
"belt": "orange",
"rate": 10,
"available": true,
"thumb": "content/img/ryu.png"
}, {
"name": "Shaun",
"belt": "black",
"rate": 1000,
"available": true,
"thumb": "content/img/shaun.png"
}]
I tried testing using both httpster and using Brackets built in live preview. I get a 404 error, but the file does for sure exist as you can see in the image
If it helps, this is my whole app.js file
var myNinjaApp = angular.module('myNinjaApp', ['ngRoute']);
myNinjaApp.config(['$routeProvider', function($routeProvider){
$routeProvider
.when('/home', {
templateUrl: 'views/home.html'
})
.when('/directory', {
templateUrl: 'views/directory.html',
controller: 'NinjaController'
})
.otherwise({
redirectTo: '/home'
});
}]);
myNinjaApp.controller('NinjaController', ['$scope', '$http', function($scope, $http){
$scope.removeNinja = function(ninja){
var removedNinja = $scope.ninjas.indexOf(ninja);
$scope.ninjas.splice(removedNinja, 1)
};
$scope.addNinja = function(){
$scope.ninjas.push({
name: $scope.newninja.name,
belt: $scope.newninja.belt,
rate: parseInt($scope.newninja.rate),
available: true
});
$scope.newninja.name = "";
$scope.newninja.belt = "";
$scope.newninja.rate = "";
};
$http.get('data/ninjas.txt').then(function(response) {
// Success!!!
$scope.ninjas = response.data;
});
}]);

To make the answer complete,
Your root of your application is 'index.html', and because Angular is running within 'index.html', all files you load in your files are relative to your 'index.html'.
An example of that is seen in your route configuration, where your templates are loaded starting at 'views/*', which is a child folder of your 'index.html'

myNinjaApp.controller('NinjaController', ['$scope', '$http', function ($scope, $http) {
$http({
url: "data/ninjas.json",
method: "GET"
}).then(function (resp) {
$scope.ninjas = resp;
}, function (resp) {
// bla bla bal
});
$scope.removeNinja = function (ninja) {
var removeNinja = $scope.ninjas.indexOf(ninja);
$scope.ninjas.splice(removeNinja, 1);
}
$scope.addNinja = function () {
$scope.ninjas.push({
name: $scope.newninja.name,
belt: $scope.newninja.belt,
rate: parseInt($scope.newninja.rate),
available: true
});
$scope.newninja.name = "";
$scope.newninja.belt = "";
$scope.newninja.rate = "";
};
$scope.removeAll = function () {
$scope.ninjas = [];
};
$scope.sort = function (keyname) {
$scope.sortKey = keyname;
$scope.reverse = !$scope.reverse;
}
}]);

As for all who struggle getting not an array with net ninjas and the code above you now get the whole HTTP response under data not the JSON file itself you need to get the data property of the request so like this:
$http.get('app/Data/ninja.json').then(function(data) {
$scope.ninjas = data.data;
}, function() {
});

Related

Angularjs using service to pass a parameter to a function

I'm fetching a Json with a factory "chapters", so I get the value of the property "json_file" which is another json file that I need to fetch dynamically with the factory "contents". I just need to pass the parameter "json_file" to the second factory, but I get an undefined value.
Maybe I need a service?
This is the first json file:
structure.js
[
{
"title": "Introduction",
"pages": [
{
"title": "Buongiorno",
"type" : "standard",
"json_file" : "cover_1"
},
{
"title": "Introduction",
"type" : "standard",
"json_file" : "cover_1"
}
]
},
{
"title": "Storytelling",
"pages": [
{
"title": "Italian Design & Swiss Watchmaking Expertise",
"type" : "standard",
"json_file" : "cover_1"
},
{
"title": "Interaction",
"type" : "standard",
"json_file" : "cover_1"
}
]
}
]
This is the controller.js
var bControllers = angular.module('bControllers',[]);
bControllers.controller('structureCtrl', function ($scope, $routeParams,chapters,contents){
$scope.indexChapter = 0;
$scope.indexPage = 0;
chapters.list(function(chapters) {
$scope.chapters = chapters;
$scope.pages = [];
$scope.json_file = [];
angular.forEach($scope.chapters, function(chapters,index){
angular.forEach(chapters.pages, function(page,index2){
$scope.pages.push(page);
$scope.json_file.push(page.json_file);
})
});
$scope.currentJson = $scope.chapters[$scope.indexChapter].pages[$scope.indexPage].json_file;
console.log('json-file:'+$scope.currentJson);
return $scope.currentJson;
});
contents.find($scope.currentJson, function(content) {
$scope.content = content;
});
});
And this is the factory.js
var bFactory = angular.module('bFactory',[]);
bFactory.factory('chapters', function($http){
return {
list: function (callback){
$http({
method: 'GET',
url: 'json/structure.json',
cache: true
}).success(callback);
}
}
});
bFactory.factory('contents', function($http){
return{
find:function(json_file, callback){
$http({
method: 'GET',
url: 'json/'+json_file+'.json',
cache: true
}).success(callback);
}
}
})

angular service test fails to return required response

I am trying to write tests for angular service using jasmine and karma. I have the following code for my service call:
angular.module('omdb', [])
.factory('myservice', MyService);
MyService.$inject = ['$http'];
function MyService($http) {
var vm = this;
var service = {};
service.getData = function() {
return $http.get('omdb/mydata.json').then(function(response) {
return response.data;
});
};
return service;
};
I am tesitng it using the following file for spec as:
describe('myservice', function() {
var mockservicedata = [{
"name": "value1",
"id": "1"
}, {
"name": "value2",
"id": "2"
}, {
"name": "value3",
"id": "3"
}];
var myservice = {};
beforeEach(module('omdb'));
beforeEach(inject(function(_myservice_) {
myservice = _myservice_;
}));
it('should return search myservice data', function() {
expect(myservice.getData()).toEqual(mockservicedata);
});
});
which basically throws an error as:
Expected d({ $$state: Object({ status: 0 }) }) to equal [ Object({ name: 'value1', id: '1' }), Object({ name: 'value2', id: '2' }), Object({ name: 'value3', id: '3' }) ].
stack#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1482:17
buildExpectationResult#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1452:14
Env/expectationResultFactory#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:583:18
Spec.prototype.addExpectationResult#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:324:29 addExpectationResult#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:533:16
Expectation.prototype.wrapCompare/<#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1406:7
#http://localhost:59239/movie-app/spec/omdb/myservice.spec.js:14:9
attemptSync#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1789:9
QueueRunner.prototype.run#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1777:9 QueueRunner.prototype.execute#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1762:5
Env/queueRunnerFactory#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:627:7
Spec.prototype.execute#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:353:5 executeNode/<.fn#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:2360:32 attemptAsync#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1819:9
QueueRunner.prototype.run#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1774:9
QueueRunner.prototype.execute#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1762:5
Env/queueRunnerFactory#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:627:7
executeNode/<.fn#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:2345:13 attemptAsync#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1819:9
QueueRunner.prototype.run#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1774:9
QueueRunner.prototype.execute#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1762:5
Env/queueRunnerFactory#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:627:7
TreeProcessor/this.execute#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:2209:7
Env/this.execute#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:678:7
window.onload#http://localhost:59239/movie-app/lib/jasmine-2.3.4/boot.js:110:5
I don't understand why it does not return data to the test. please help
Calling myservice.getData() won't actually give you the data you're expecting.
Since your getData method from MyService relies on $http's get method, you should be mocking it and then expecting that data returned.
So your test case should be like:
describe('myservice', function() {
var mockservicedata = [{
"name": "value1",
"id": "1"
}, {
"name": "value2",
"id": "2"
}, {
"name": "value3",
"id": "3"
}];
var myservice = {};
beforeEach(module('omdb'));
beforeEach(inject(function(_myservice_, _$httpBackend_) {
myservice = _myservice_;
$httpBackend = _$httpBackend_;
$httpBackend.when('GET', "omdb/mydata.json").respond({
status: 200,
data: mockservicedata
});
}));
it('should return search myservice data', function() {
var response = myservice.getData()
response.then(function(response) {
expect(response.data).toEqual(mockservicedata);
});
$httpBackend.flush();
});
});
Hope this helps.
getData() will never return data instead it will return promise object.
If you want to test it then firstly you would have to mock the data for service then you can call it and match the result in the success handler.
Code is attached below:
describe('myservice', function() {
var mockservicedata = [{
"name": "value1",
"id": "1"
}, {
"name": "value2",
"id": "2"
}, {
"name": "value3",
"id": "3"
}];
var myservice, httpBackend;
beforeEach(module('omdb'));
beforeEach(inject(function(_myservice_, $httpBackend) {
myservice = _myservice_;
httpBackend = $httpBackend;
}));
it('should return search myservice data', function() {
httpBackend.when("GET", "omdb/mydata.json").respond(mockservicedata);
var promise = myservice.getData();
promise.then(function(response) {
expect(response.data).toEqual(mockservicedata);
});
httpBackend.flush();
});
});

UI-Grid not displaying JSON data?

I have what I think is the correct accessor syntax for binding my UI-Grid control, I don't get any errors or any data. I just get a warning about Mutating the prototype.
My json data structure is like this:
{
"records": [
{
"acctIdInfo": {
"acctId": "257905480",
"acctCode": "ABC10101102",
"acctName": "BIG CORPORATION",
"acctRole": [
"C"
]
},
"acctNameAddr": {
"addressLine": [
"7280 JAMISON ST"
],
"cityName": "VANCOUVER",
"stateCd": "US-WA",
"countryCd": "US",
"postalCd": "97979"
}
}
]
}
The code in my AngularJS controller to bind is:
var app = angular.module('app', ['ui.grid', 'ngResource'])
.factory('jsonDataFactory', function ($resource) {
return {
custData: $resource('data.json', {}, {
query: {method: 'GET', params: {}, isArray: false}
}),
};
});
app.controller('MainCtrl', ['$scope','$resource','jsonDataFactory', function ($scope,$resource, jsonDataFactory) {
$scope.gridOptions = {
enableRowSelection: true,
enableSelectAll: true,
selectionRowHeaderWidth: 35
};
$scope.gridOptions.columnDefs = [
{ name: 'acctIdInfo.acctId' },
{ name: 'acctIdInfo.acctCode'},
{ name: 'acctIdInfo.acctName'},
{ name: 'acctNameAddr.addressLine' }
];
$scope.gridOptions.data = jsonDataFactory.custData.query().records;
$scope.CustomerData = [];
$scope.CustomerData = jsonDataFactory.custData.query();
console.log($scope.CustomerData);
$scope.gridOptions.data = $scope.CustomerData.records;
}]);
Here is my plnk of what I tried -
I think I'm close...
Do assign a data to ui-grid data source once ajax call response comes back. I assumed that you had used $resource, so you can have promise over it to attach callback function.
jsonDataFactory.custData.query().$promise.then(function(response){
$scope.CustomerData = response;
console.log($scope.CustomerData);
$scope.gridOptions.data = $scope.CustomerData.records;
});

Stuck: AngularJs using factory with http call to json

I am struck and not able to understand the issue here.
I created a factory using http service call to my json file
Factory (accountInfo.json):
appRoot.factory('accountInfo', ['$http', function($http) {
return $http.get('../../accountInfo.json')
.success(function(data) {
return data;
})
.error(function(err) {
return err;
});
}]);
controller(AccountsController.js)
appRoot.controller('AccountsController', ['$scope', 'accountInfo', function($scope, accountInfo){
accountInfo.success(function(data) {
$scope.rows = data;
});
$scope.totals = {
name: '',
marketValue: 0,
cash: 0,
legend: 'none'
};
for (var i = 0; i < $scope.rows.length; i++) {
$scope.totals.marketValue += $scope.rows[i].marketValue;
$scope.totals.cash += $scope.rows[i].cash;
}
$scope.addAccount = function() {
$scope.rows.push({
name: 'New Account',
marketValue: Math.random() * 100000,
cash: Math.random() * 400000,
legend: 'cyan'
});
}
}]);
My json (accountInfo.json)
[{
"name": "Brokerage Account 3",
"marketValue": 1999990,
"cash": 1995826,
"legend": "orange"
},
{
"name": "Account 3",
"marketValue": 1949990,
"cash": 1695856,
"legend": "darkorange"
},
{
"name": "Brokerage Account 1",
"marketValue": 1349990,
"cash": 1595866,
"legend": "red"
},
{
"name": "Brokerage Account 4",
"marketValue": 155990,
"cash": 160826,
"legend": "blue"
},
{
"name": "Brokerage Account 2",
"marketValue": 74560,
"cash": 19956,
"legend": "gray"
},
{
"name": "Account 4",
"marketValue": 55006,
"cash": 53006,
"legend": "salmon"
},
{
"name": "Account 13",
"marketValue": 37340,
"cash": 0,
"legend": "green"
},
{
"name": "Joint Account 1",
"marketValue": 28308,
"cash": 4167,
"legend": "darkblue"
},
{
"name": "Joint Account 2",
"marketValue": 10000,
"cash": 10000,
"legend": "teal"
}]
Error I am receiving is "$scope.rows is undefined"
Controller is not able to access $scope.rows outside success function.
Thanks :)
You need to resolve the promise in your controller, not in your factory, just return the promise:
appRoot.factory('account', ['$http', function($http) {
return {
info: function () {
return $http.get('../../accountInfo.json');
}
}
}]);
Then in your controller do:
appRoot.controller('AccountsController', ['$scope', 'account', function($scope, account){
account.info()
.success(function(data) {
$scope.rows = data;
})
.error(function(err) {
return err;
});
}]);
FYI, the success and error methods are deprecated:
The $http legacy promise methods success and error have been deprecated. Use the standard then method instead. If $httpProvider.useLegacyPromiseExtensions is set to false then these methods will throw $http/legacy error.
See: https://docs.angularjs.org/api/ng/service/$http
Use the then method:
account.info().then(
function resolved (response) {
$scope.rows = response.data;
},
function rejected (response) {
alert(response.status + ': ' + response.statusText);
}
);
Here's a working example of the concept: http://plnkr.co/edit/UtJDpvBKKYl4rBzgXYo4?p=preview
You should return a function which fetches the data when you call it like so:
appRoot.factory('accountInfo', ['$http', function($http) {
return {
fetchData: fetchData
};
function fetchData() {
return $http.get('../../accountInfo.json');
}
}]);
then in your controller you can do:
accountInfo.fetchData()
.then(
function(data) {
console.log(data);
},
function(error) {
console.log(error);
}
);
Thank you all for the help.
I solved my issues by bootstraping the app. I was not able to access my data initially since the http call was not completed.
angular.element(document).ready(function() {
angular.bootstrap(angular.element(document), ['app']);
});

Server always throws 403 on Angularjs ajax call in Django

Server always throws 403 in my Django app. I tried using csrf along with the data that is being posted to server, but still no luck. What am I missing ?
Here is how am invoking the $http service function
<body ng-controller="rdCtrl">
<a ng-click="saveprof()">Save</a>
<script>
var app = angular.module('rdExampleApp', ['ui.rdplot']);
app.controller('rdCtrl', function ($scope, $http) {
$scope.dataset = {
"d0": { "id": 0, "name": "Housing", "value": 18 },
"d1": { "id": 1, "name": "Travel", "value": 31.08 },
"d2": { "id": 2, "name": "Restaurant", "value": 64 },
"d3": { "id": 3, "name": "Bank", "value": 3 },
"d4": { "id": 4, "name": "Movies", "value": 10 }
};
$scope.func = function func() {
var jdata = $scope.dataset;
return jdata;
}
$scope.saveprof = function () {
//show spinner
$('.spinner').show();
$http.post('saveprof', {
data: { 'data': $scope.dataset},
'csrfmiddlewaretoken': $("input[name=csrfmiddlewaretoken]").val()
})
.success(function (data) {
if (data == "null") {
//your code if return data empty
} else {
//your code if return data not empty
$('#message').html(data);
}
//hide spinner
$('.spinner').fadeOut();
})
.error(function (data, status, headers, config) {
console.log('error' + status);
//hide spinner in case of error
$('.spinner').fadeOut();
})
});
</script>
</body>
Edit:
I corrected it, ajax call is being invoked when I click on button - but it returns 403 error.. Access forbidden.. I have view saveprof in my django views.. and also I used csrf token.. Am not sure why server returns 403. (http:/x.x.x.x/saveprof)
What am I missing?
you have to inject $http to the controller as parameter
app.controller('rdCtrl', function ($scope, $http) { .. }

Resources