I am following the basic Angular tutorial and need to include a JSON file in it.
I kickstarted my application with Yeoman and it is running on grunt.
var phonecatApp = angular.module('phonecatApp', []);
phonecatApp.controller('PhoneListCtrl', function PhoneListCtrl($scope) {
$http.get('phones/phones.json').success(function(data) {
$scope.phones = data;
});
});
However when I go to localhost:9000 I get a bunch of console errors:
ReferenceError: $http is not defined
at new PhoneListCtrl (http://localhost:9000/scripts/controllers/main.js:17:3)
at invoke (http://localhost:9000/bower_components/angular/angular.js:3000:28)
at Object.instantiate (http://localhost:9000/bower_components/angular/angular.js:3012:23)
at http://localhost:9000/bower_components/angular/angular.js:4981:24
at http://localhost:9000/bower_components/angular/angular.js:4560:17
at forEach (http://localhost:9000/bower_components/angular/angular.js:137:20)
at nodeLinkFn (http://localhost:9000/bower_components/angular/angular.js:4545:11)
at compositeLinkFn (http://localhost:9000/bower_components/angular/angular.js:4191:15)
at compositeLinkFn (http://localhost:9000/bower_components/angular/angular.js:4194:13)
at publicLinkFn (http://localhost:9000/bower_components/angular/angular.js:4096:30)
Any help would be appreciated!
It may be better for you to include the json file in a factory service. That way you can cache it and continue to use it with different controllers.
I had a similar issue and resolved it like so...
var App = angular.module('App', []);
// Setting up a service to house our json file so that it can be called by the controllers
App.factory('service', function($http) {
var promise;
var jsondata = {
get: function() {
if ( !promise ) {
var promise = $http.get('src/data_json.js').success(function(response) {
return response.data;
});
return promise;
}
}
};
return jsondata;
});
App.controller('introCtrl', function (service , $scope) {
service.get().then(function(d) {
$scope.header = d.data.PACKAGE.ITEM[0]
})
});
App.controller('secondCtrl', function (service , $scope) {
service.get().then(function(d) {
$scope.title = d.data.PACKAGE.ITEM[1]
})
});
Add $http as dependency, next to $scope in your function PhoneListCtrl($scope, $http) {}
Related
I'm creating a service on a separate module called 'hsHttp' -> HttpSrv. And I'm trying to use it from another module 'HttpApp'. I'm getting injector error: Error: [$injector:unpr]
My code is below:
"file1.js" => The service implementation
(function () {
var app = angular.module("hsHttp", []);
app.service("HttpSrv", function ($scope, $http) {
....
});
})();
"file2.js" => The service use implementation
(function () {
var app = angular.module("HttpApp", ["hsHttp"]);
app.controller("HttpCtrl", HttpCtrl);
function HttpCtrl($scope,HttpSrv) {
...
}
})();
Why Angular can't inject the service from the other module ?
Thanks.
/yore
The problem is: service does not accept $scope as dependency. The solution is to remove the $scope from the definition:
(function () {
var app = angular.module("hsHttp", []);
app.service("HttpSrv", function ($http) {
....
});
})();
I have an app that I have inherited that I have to support. So far it had only run on one server and we want to run it on different servers. We found hard coded references to the server name all over the place in python server code and C++ client code. It was easy enough to change those to read the server name from a config file. But now I find is a js module this code:
angular.module('app.config', []).constant('config', {"api":"http://foo.bar.com:8001/"});
How can I change this so that the value for the server is read dynamically from a config file or some other means that would not require it to be hard coded?
Here is an update with what I have tried:
Originally, my code had this:
angular.module('app.config', []).constant(
'config', {"api":"http://foo.bar.com:8001/"}
);
and I changed it to this:
angular.module('app.config').controller('myCtrl',
function($scope, $http) {
$http.get('./config.json')
.then(function(response) {
$scope.api = response.data;
});
});
and I got this:
error Module 'app.config' is not available!
Then I changed it to:
angular.module('app.config', [] ).controller('myCtrl',
function($scope, $http) {
$http.get('./config.json')
.then(function(response) {
$scope.api = response.data;
});
});
And then I get:
Error: [$injector:unpr] Unknown provider: configProvider <- config <- workitem
I feel I am very close, I just need a bit more help.
Another update:
I tried this:
angular.module('app').controller('home', ['$scope', homeCtrl]);
angular.module('app').controller('workitem', ['$scope', '$routeParams', '$sce', '$timeout', '$http', 'config', workitemCtrl]);
},{"./home/home.js":3,"./workitem/workitem.js":4,"angular":10,"angular-route":6,"angular-sanitize":8,"bootstrap-treeview/src/js/bootstrap-treeview.js":11}],2:[function(require,module,exports){
module.exports = function($scope,$http) {
$http.get('config.json').success(function(reponse) {
console.log("reponse --> "+reponse.api);
$scope.api = reponse.api;
});
}
But then of course app.config was not getting defined. How could I do this an still define app.config?
I just tried this:
var my_config = {};
$.getJSON("config.json", function(data) {
$.each(data, function(key, val) {
my_config[key] = val;
});
});
but I get my_config is not defined when I use it down in the controller. How can I make that variable available in the controller?
Try This
angular.module('app.config', [])
.constant('bbConfig',{
"api":"http://foo.bar.com:8001/"
});
In controller
angular.module('app.config', [])
.controller('MainCtrl',['$scope', 'bbConfig' , function ($scope, bbConfig){
console.log(bbConfig.api)
}]);
Create a service to read the config (json file) or make a call to server and store the response URL in LocalStorage like the following. You can access it from every where
$localStorage.api = response.Url ; // http://foo.bar.com:8001/
I was finally able to get this working by doing this up front:
angular.module('app').value('config', {
api: ''
});
angular.module('app').run(function($rootScope, $http, config) {
$http.get('config/config.json').then(function(response) {
config.api = response.data.api;
$rootScope.$broadcast('config-loaded');
});
});
Wrapping the main code in:
var init = function(){
}
And adding this at the end:
if (config.api) {
init()
} else {
var configLoaded = scope.$on('config-loaded', function() {
init();
configLoaded();
});
}
You can do:
Use ngConstant build task to wrap your standalone config file in JSON format into the includable angular.config data.
Suppose you have app/config.json file:
{
"myFirstCnt": true,
"mySecondCnt": { "hello": "world" }
}
Then after running the ngConstant task in you build you'll get dist/config.js (output) will be :
define(["require", "exports"], function(require, exports) {
return angular.module("my.module.config", ["ngAnimate"])
.constant("myFirstCnt", true)
.constant("mySecondCnt", { "hello": "world" })
.constant("myPropCnt", "hola!");
});
Gulp plugin, Grunt plugin, more on ngConstant
Use service to load the JSON file immediately after you app bootstraps in service or in the controller:
should avoid this:
app.controller('myCtrl',
function($scope, $http) {
$http.get('PATH_TO/config.json').then(function(response) {
$scope.myWelcome = response.data;
});
}
);
More on that way example here: Reading in JSON through Angular Resources Service
UPD 12-06
For parsing loaded JSON try this:
for (var name in data) {
if (data.hasOwnProperty(var)) {
my_config[var] = data[var];
}
}
I'm working on a mobile app using AngularJS as a framework, currently I have a structure similar to this:
app.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/', {
templateUrl : 'pages/home.html',
controller : 'homeCtrl'
})
.when('/one', {
templateUrl : 'pages/one.html',
controller : 'oneCtrl'
})
.when('/two', {
templateUrl : 'pages/two.html',
controller : 'twoCtrl'
});
}]);
app.controller('homeCtrl', ['$scope', function($scope) {
}]);
app.controller('oneCtrl', ['$scope', function($scope) {
}]);
app.controller('twoCtrl', ['$scope', function($scope) {
}]);
And then I'm displaying the content with an ng-view:
<div class="ng-view></div>
Things are working well but I need to load data from a JSON file to populate all the content of the app. What I want is to make and an AJAX call only once and then pass the data through all my different controllers. In my first attempt, I thought to create a Service with an $http.get() inside of it and include that in every controller, but it does not work because it makes a different ajax request everytime I inject and use the service. Since I'm new using angular I'm wondering what is the best way or the more "angular way" to achieve this without messing it up.
Edit: I'm adding the code of the service, which is just a simple $http.get request:
app.service('Data', ['$http', function($http) {
this.get = function() {
$http.get('data.json')
.success(function(result) {
return result;
})
}
});
Initialize the promise once, and return a reference to it:
No need to initialize another promise. $http returns one.
Just tack a .then() call on your promise to modify the result
angular.module('app', [])
.service('service', function($http){
this.promise = null;
function makeRequest() {
return $http.get('http://jsonplaceholder.typicode.com/posts/1')
.then(function(resp){
return resp.data;
});
}
this.getPromise = function(update){
if (update || !this.promise) {
this.promise = makeRequest();
}
return this.promise;
}
})
Codepen example
Edit: you may consider using $http cache instead. It can achieve the same results. From the docs:
If multiple identical requests are made using the same cache, which is not yet populated, one request will be made to the server and remaining requests will return the same response.
Try this to get JSON Data from a GET Link:
(function (app) {
'use strict';
app.factory('myService', MyService);
MyService.$inject = ['$q', '$http'];
function MyService($q, $http) {
var data;
var service = {
getData: getData
};
return service;
//////////////////////////////////////
function getData(refresh) {
if (refresh || !data) {
return $http.get('your_source').then(function(data){
this.data = data;
return data;
})
}
else {
var deferrer = $q.defer();
deferrer.resolve(data);
return deferrer.promise;
}
}
}
}(angular.module('app')));
Now you can add this dependency in your controller file and use:
myService.getData().then(function(data){
//use data here
}, function(err){
//Handle error here
});
I have a simple service which grab data from HTTP end point send it back to controller.
I also implemnted caching in the service however, i get this error TypeError: undefined is not a function on this line of code in my controller
myappApi.getItems().then(function(data)
I tried to figure out why i couldn't.
here is the controller code:
.controller('ItemsCtrl',['$scope','myappApi',function($scope, myappApi){
myappApi.getItems().then(function(data){
$scope.items = data;
});
}])
As am using Ioniframework here how i injected my services in the app.js:
angular.module('myApp', ['ionic', 'myApp.controllers', 'myApp.services', 'angular-data.DSCacheFactory'])
and here is the code of my service:
(function() {
'use strict';
angular.module('myApp.services',[]).factory('myappApi', ['$http', '$q', '$ionicLoading', 'DSCacheFactory', myappApi]);
function myappApi($http, $q, $ionicLoading, DSCacheFactory) {
self.itemsCache = DSCacheFactory.get("itemsCache");
//to re-use expired cached data if no internet connection
self.itemsCache.setOptions({
onExpire: function (key, value) {
getItems()
.then(function () {
console.log("items items Cache was automatically refreshed.", new Date());
}, function () {
console.log("Error getting data. Putting expired item back in the cache.", new Date());
self.itemsCache.put(key, value);
});
}
});
function getItems() {
var deferred = $q.defer(),
cacheKey = "items",
itemsData = self.itemsCache.get(cacheKey);
if (itemsData) {
console.log("Found data inside cache", itemsData);
deferred.resolve(itemsData);
} else {
$http.get("services/data.json")
.success(function(data) {
console.log("Received data via HTTP");
self.itemsCache.put(cacheKey, data);
deferred.resolve(data);
})
.error(function() {
console.log("Error while making HTTP call.");
deferred.reject();
});
}
return deferred.promise;
}
return {
getItems: getItems
};
};
})();
Thank you for your time.
Take a look in the angular-cache file CHANGELOG.md :
"- Angular module renamed to angular-cache
- DSCacheFactory renamed to CacheFactory"
You will have to change:
app.js:
instead of 'angular-data.DSCacheFactory' use 'angular-cache'
service.js
instead of 'DSCacheFactory' use 'CacheFactory'
It looks like you've declared the myappApi factory before the myappApi function is actually defined. Try something like:
angular.module('myApp.services',[]).factory('myappApi', ['$http', '$q', '$ionicLoading', 'DSCacheFactory',
function($http, $q, $ionicLoading, DSCacheFactory) {
// myappApi code
}]);
How load $http service app on startup in Ionic framework?
// This is a service
appModule.factory('NewGames', function($http, $ionicLoading) {
// JSON Array
var newGames = [];
var request = {'searchString' : 'name_fr'};
$http.get('http://example.com/rest/data.php', { cache: true}, request).success(function(response) {
newGames = response;
});
return {
all: function() {
//$ionicLoading.hide();
return newGames;
}
}
});
// This is a controller
myApp.controller('MainCtrl', function($scope, NewGames, $ionicSlideBoxDelegate, $stateParams, $ionicPlatform) {
$scope.nextSlide = function() {
$ionicSlideBoxDelegate.next();
}
$scope.newGames = NewGames.all();
});
If you press the button, the data is loaded. How to make so that the data was loaded at startup?
Use the ionic.Platform.ready() method, documented here.
You can run this method from anywhere in your app, may it be factory or controller.