I am following this AngularJS Tutorial.
I am successfully able to display a data model array list in the browser (Chrome 37.0.2062.94) when instantiated using object literal notation, where $scope.sentences is of type "Object".
Controller: (extract)
'use strict';
angular.module('YeomanIonic.controllers', [])
.controller('MapCtrl', ['$scope', '$ionicLoading', '$http', function($scope, $ionicLoading, $http) {
$scope.sentences = [
{"name": "Hello",
"snippet": "1"
},
{"name": "Goodbye",
"snippet": "2"
}
];
}]);
View (extract):
<body ng-app="YeomanIonic" ng-controller="MapCtrl">
<ul>
<li ng-repeat="sentence in sentences">
<span>{{sentence.name}}</span>
<p>{{sentence.snippet}}</p>
</li>
</ul>
But I get problems when I instead store this array of hashes in a JSON file (i.e. app/data/sentences.json), as follows:
sentences.JSON:
[
{"name": "Hello",
"snippet": "1"
},
{"name": "Goodbye",
"snippet": "2"
}
];
I attempt to use the AngularJS $http service to perform a HTTP GET request to fetch this JSON data. The tutorial mentions that AngularJS detects and parses the JSON response automatically and that the $http service returns a promise object with a success method. So I assumed that the following code would work correctly such that $scope.sentences would be of type "Object", however it informs me that it is of type "String".
$http({
method: 'GET',
url: 'data/sentences.json'
}).
success(function(data, status, headers, config) {
console.log("HTTP Request - Success");
$scope.sentences = data;
console.log(typeof($scope.sentences));
}).
error(function(data, status, headers, config) {
console.log("HTTP Request - Error");
});
So I attempted to assign it with this following code instead, which gives the following error:
$scope.sentences = angular.fromJson(data);
SyntaxError: Unexpected token ;
at Object.parse (native)
at Object.fromJson (http://127.0.0.1:9000/bower_components/angular/angular.js:1139:14)
at http://127.0.0.1:9000/scripts/controllers.js:34:59
at http://127.0.0.1:9000/bower_components/angular/angular.js:8105:11
at wrappedCallback (http://127.0.0.1:9000/bower_components/angular/angular.js:11561:81)
at wrappedCallback (http://127.0.0.1:9000/bower_components/angular/angular.js:11561:81)
at http://127.0.0.1:9000/bower_components/angular/angular.js:11647:26
at Scope.$eval (http://127.0.0.1:9000/bower_components/angular/angular.js:12673:28)
at Scope.$digest (http://127.0.0.1:9000/bower_components/angular/angular.js:12485:31)
at Scope.$apply (http://127.0.0.1:9000/bower_components/angular/angular.js:12777:24) angular.js:10061
I try the below alternative with quotations included, which gives the following error (which is getting confused with the letter 'd' in the word 'data') :
$scope.sentences = angular.fromJson('data');
SyntaxError: Unexpected token d
at Object.parse (native)
at Object.fromJson (http://127.0.0.1:9000/bower_components/angular/angular.js:1139:14)
at http://127.0.0.1:9000/scripts/controllers.js:34:59
at http://127.0.0.1:9000/bower_components/angular/angular.js:8105:11
at wrappedCallback (http://127.0.0.1:9000/bower_components/angular/angular.js:11561:81)
at wrappedCallback (http://127.0.0.1:9000/bower_components/angular/angular.js:11561:81)
at http://127.0.0.1:9000/bower_components/angular/angular.js:11647:26
at Scope.$eval (http://127.0.0.1:9000/bower_components/angular/angular.js:12673:28)
at Scope.$digest (http://127.0.0.1:9000/bower_components/angular/angular.js:12485:31)
at Scope.$apply (http://127.0.0.1:9000/bower_components/angular/angular.js:12777:24) angular.js:10061
I try this third alternative, which gives the same as the previous error:
$scope.sentences = window.JSON.parse('data');
I try a fourth alternative, which also gives the same as the previous error:
$scope.sentences = JSON.parse('data');
With little hope left I came across this [lifesaver post] (https://stackoverflow.com/a/6487190/3208553) that mentioned using eval('data'), but which also mentions that it presents a security risk, but I gave it a shot with:
$scope.sentences = eval(data);
And this works!! It successfully grabs and displays the data from the JSON file as a list in the browser. Note that when I check what it assigns with console.log(eval(data)); it gives me [object Object],[object Object],[object Object],[object Object]
But I can't celebrate because I don't understand why the other alternatives that I tried didn't work...
So my questions to the community are:
- Why doesn't the AngularJS $http service detect and parses the JSON response automatically and return it as an Object (instead of a String)?
- Why doesn't the AngularJS fromJSON deserialize the JSON string without an error? (which appears to simply perform JSON.parse('') according to its Source Code)
- Is my JSON encoding competent and are my inputs incorrectly validated in this simple example? Is this why only the unsafe 'eval' method works for me (with its associated security risks)?
FYI, Here is the latest commit to my Ionic app associated with this post on GitHub