I am having trouble with injecting my service in angular that gives me $injector:unpr error. Here is my code:
(function () {
/**
* This is a service to perform the backend REST calls for a Release
*/
'use strict';
angular.module('app.services')
.service('ReleaseService', ReleaseService);
ReleaseService.$inject = ['$http'];
function ReleaseService () {
var releaseService = {};
var releasesUrl = 'http://localhost:8080/api/releases';
releaseService.releases = getReleases;
return releaseService; // return the release service object to the controller
/**
* Get the list of the releases. Does an HTTP GET request to the backend
* #returns {Array} of releases to the caller of the service
*/
function getReleases(){
var releases = [];
$http.get(releasesUrl).then(function(responseData){
//check the status from the response data.
if(responseData.status !== 200){
alert('The request could not be completed. Please try again');
} else{
// else, Parse the json data here and return to the service caller
for(var release in responseData.data){
releases.push({slug: release, data: responseData.data[release]});
}
}
});
return releases;
}
// This is the controller.js file where I inject the service I created above
(function (){
angular.module('app.uploadedReleases')
.controller('UploadedReleasesController', UploadedReleasesController)
.controller('ModalController', ModalController);
UploadedReleasesController.$inject = ['$log', '$scope', '$modal', 'ReleaseService', 'TrackService'];
function UploadedReleasesController ($log, $scope, $modal, releaseService, TrackService){
function init(){
var something = releaseService.releases();
}
}
Any idea what am I possibly missing ?
Thanks for the inputs folks. I think I was missing the registering the app.services in my main app module. Doing this solved the problem.
Related
I have two controllers both with a save button which essentially does the same thing. So I want to put it in a reusable function that both the controllers can use. I have tried to do this by creating a normal function and passing the model object, as well as $http, but the function is executing before the save button is pressed leading to all the params being set to undefined. What way should I create a function that both these controllers can use?
Here how code looks:
app.controller('addCtlr',['$scope','$http','$location',
function($scope, $http, $location){
$scope.save = function(){
var practices = [];
var url = "https://maps.googleapis.com/maps/api/geocode/json?address="+$scope.location.address.replace(/ /g,"+");
//If there are practices
if($scope.days){
for(dayName in $scope.days){ //Loop through the days object
var day = $scope.days[dayName]; //Gets the day pratice object
practices.push({day: dayName, start_time: day.startTime, end_time: day.endTime}); //Add the pratice object to the practices array
}
}
//Call to get the lat lng and formatted address from Google Map's service
$http.get(url)
.then(function(response){
locJSON = response.data.results[0]; //The JSON response
//createing an object to send to the backend to save
var locObj = {
name: $scope.location.name,
address: locJSON.formatted_address,
location: locJSON.geometry.location,
cost: $scope.location.cost,
practices: practices,
notes: $scope.location.notes
};
//Sending using POST since a new object is being created
$http.post('/api/locations', locObj)
.then(
$location.path('/')
);
});//*/
};
}]);
This is how my function looked:
function saveLocation(location, days, $http){
var practices = [];
var url = "https://maps.googleapis.com/maps/api/geocode/json?address="+location.address.replace(/ /g,"+");
//If there are practices
if(days){
for(dayName in days){ //Loop through the days object
var day = days[dayName]; //Gets the day pratice object
practices.push({day: dayName, start_time: day.startTime, end_time: day.endTime}); //Add the pratice object to the practices array
}
}
//Call to get the lat lng and formatted address from Google Map's service
$http.get(url)
.then(function(response){
locJSON = response.data.results[0];
//createing an object to send to the backend to save
var locObj = {
name: location.name,
address: locJSON.formatted_address,
location: locJSON.geometry.location,
cost: location.cost,
practices: practices,
notes: location.notes
};
//Sending using POST since a new object is being created
$http.post('/api/locations', locObj)
.then(
//$location.path('/') //Redirects the user back to the homepage
);
});
}
This is how I was calling the function in the new controller:
app.controller('addCtlr',['$scope','$http','$location',
function($scope, $http, $location){
$scope.save = saveLocation(location, days, $http);
}]);
You can use service for this. Service is a singleton so will be created only one instance. And You can inject it by a dependency injector to controllers. You can read more here
You can create a service for your shared functionality and can inject it into your controller like below
var app=angular.module('app',[])
app.service('myService',function($http){
this.saveLocation=function(){
//Your code
}
});
and then in your controller you can inject it like below
app.controller('myController',['$scope','myService',function($scope,myService){
//use myService function to call save functionality
}]);
Also if you are using $http, you should keep this in mind that it returns a promise so you need to write all the code which is dependent on the value of this promise in a success callback otherwise your code will run before this callback and you will have undefined values for those variables.
Use a factory() service. You can define a set of functions and return them as an object. This object can then be injected within any controller:
app.factory('sharedFactory', [function() {
"use strict";
return {
myFunction: function() {
console.log("sharedFunction");
}
};
}]);
app.controller('AnyController', ['sharedFactory', function(sharedFactory) {
"use strict";
sharedFactory.myFunction();
}]);
I am attempting to simply throw some JSON data onto a page from a GET call.
This is my HTML (Please be aware this is loaded into index.html which has the correct angular notation):
<h1>Downloads</h1>
<div class="container" ng-controller="DownloadCtrl as download">
<p>{{download.routes}}</p>
</div>
This is the download controller:
(function(){
'use strict';
angular.module('dashboardApp').controller('DownloadCtrl', DownloadCtrl);
DownloadCtrl.$inject= ['DownloadService'];
function DownloadCtrl(DownloadService){
var self = this;
self.routes = function(){
DownloadService.getRoutes()
.then(function(responseData) {
self.routes = responseData;
});
};
};
})();
This is the download service:
(function(){
'use strict';
angular.module('dashboardApp')
.factory('DownloadService', DownloadService);
DownloadService.$inject = ['$http', '$sessionStorage'];
var baseURL = 'http://localhost:8080/Dashboard/rest/download/';
function DownloadService ($http, $sessionStorage){
var service = {};
service.getRoutes = getRoutes;
return service;
function getRoutes(){
return $http.get(baseURL+"route",$sessionStorage.sessionData.sessionID);
}
}
})();
I have debugged the application and it does hit self.routes however it just skips over it and no data is displayed.
I also am not receiving any errors in the console. It just skips over the function.
This is my first AngularJS application.
Your code is bad organized,
the error resides in the view, because it is not calling the method self.routes, it is just printing out...
your view must do something like that:
<p>{{download.routes()}}</p>
But, this is a bad way to code...
Please, consider doing something like that:
DownloadService
.getRoutes()
.then(function(responseData){
self.routes = responseData;
})
;
// instead of
self.routes = function(){
DownloadService.getRoutes()
.then(function(responseData){
self.routes = responseData;
});
};
I am trying to create a user profile page. Where User can display and edit their information.
This is my Controller.js
var userProfileControllers = angular.module("userProfileControllers", []);
userProfileControllers.controller ('userProfileCtrl', ['$scope', '$location', 'localCache', 'customersignup', function ($scope, $location, localCache, customersignup){
var submitProfile = function() {
//Bind Scope
//
var bindScope = function () {
$scope.userProfile = customersignup.userProfile;
};
var asyncBindScope = function() {
$scope.$evalAsync(bindScope());
};
bindScope ();
}}]);
This is my service.js
var userProfileServices = angular.module("userProfileServices", []);
userProfileServices.factory("customersignup", function() {
return {
userProfile: {fname: "kunal"},
updateProfile: function() {
var userProfile = this.userProfile;
},
}
});
In the HTML, let's say in case of first name I have included ng-model="userProfile.fname" in the input of First Name field. Now, when I am loading the html page, I am getting this error :-
https://docs.angularjs.org/error/$injector/unpr?p0=localCacheProvider%20%3C-%20localCache%20%3C-%20userProfileCtrl
Please check the above link, it is from AngularJS official site.
check you have two modules one is for service and other one is for controller, and note that there is no glue between these two modules, to work this you need to glue these two modules, to do that, import the service module in to controller module as below.
var userProfileControllers = angular.module("userProfileControllers", ['userProfileServices']);
then module userProfileControllers have access to module userProfileServices which service is defined. Other vice you don't have access to service module userProfileServices.
You have to add factory name in controller userProfileServices
I'm looking for a way to cache language translation in angular js application.
In the application, there are many form that need translation. To get the available languages, I use $resource to get them from our Language API.
First, I create an empty array of languages on application run()
angular
.module('admin', [])
.run(['$rootScope',
function($rootScope) {
$rootScope.languages = [];
}
)
;
Then I create a service to handle translation and language query
angular
.module('admin')
.factory('Utils', ['$rootScope', 'Language',
function($rootScope, Language) {
var utils = {};
utils.getLanguages = function() {
if ($rootScope.languages.length > 0) {
return $rootScope.languages;
}
var languages = Language.query(function(data) {
$rootScope.languages = data;
});
return languages;
}
return utils;
}
)
;
and in the controller
angular
.module('admin')
.controller('CategoryController', ['$scope', 'Utils',
function($scope, Utils) {
$scope.languages = Utils.getLanguages();
}
])
;
That's the way I cache the $resource result.
What do you think about this solution?
Is it ok to cache in $rootScope?
The reason I want to cache the result because I need the languages in most of the controller, so I don't want to make request for the Language API everytime I access a new state.
There as some improvement that you can do with your implementation.
You don't need to use $rootScope for saving language and then exposing it through a service. You can very well use a service and cache the results in the service.
Something like this should be better option
angular.module('admin')
.factory('LanguageCache', ['$rootScope', 'Language',
function ($rootScope, Language) {
var service = {};
var cache;
service.getLanguages = function () {
if (cache) {
return cache;
}
var languages = Language.query(function (data) {
cache = data;
});
return cache;
}
return service;
});
This way the language cache will be available for services that want it. It will not pollute the global $rootScope object.
I want build some simple cache in Angularjs service for data provide from http request. Additional I want always get reference to the same object. I prepare example code to illustrate my thinking and problem which I have now.
jsfiddle code illustrate problem
I have service UsersModel which provide me user from http request.This user data are shared between controllers. So want to have always reference to same data. I add to him simple logic. Before UsersModel.getUsers() call service check if exist any data from previous call, if exist return him, if not do a http request. I inject that service in tree controller. In first two controllers UsersModel.getUsers() is call immediately after page load. In last after click on button.
Problem is when two first controller call UsersModel.getUsers() in the same time. Then any cached data don't exist and both do http request After that I have in first two controller reference to different user objects. We can see this clicking on load button.
And now my question. How to make this work for the simultaneous first call UsersModel.getUsers() and always have reference to the same object data.
app.js
var APP = angular.module('APP', []);
APP.SidebarCtrl = function ($scope, UsersModel) {
var sidebarCtrl = this;
UsersModel.getUsers()
.then(function (users) {
sidebarCtrl.users = users;
});
};
APP.ContentCtrl = function ($scope, UsersModel) {
var contentCtrl = this;
UsersModel.getUsers()
.then(function (users) {
contentCtrl.users = users;
});
};
APP.FootCtrl = function ($scope, UsersModel) {
var footCtrl = this;
function load() {
UsersModel.getUsers()
.then(function (users) {
footCtrl.users = users;
});
}
footCtrl.load = load
};
APP.service('UsersModel', function ($http, $q) {
var model = this,
URLS = {
FETCH: 'http://api.randomuser.me/'
},
users;
function extract(result) {
return result.data.results['0'].user.email;
}
function cacheUsers(result) {
users = extract(result);
return users;
}
model.getUsers = function () {
return (users) ? $q.when(users) : $http.get(URLS.FETCH).then(cacheUsers);
};
});
Index.html
<div ng-app="APP">
<div ng-controller="APP.SidebarCtrl as sidebarCtrl">
<h1>{{ sidebarCtrl.users }}</h1>
</div>
<div ng-controller="APP.ContentCtrl as contentCtrl">
<h1>{{ contentCtrl.users }}</h1>
</div>
<div ng-controller="APP.FootCtrl as footCtrl">
<h1>{{ footCtrl.users }}</h1>
<button ng-click="footCtrl.load()" type="button">Load</button>
</div>
</div>
jsfiddle code illustrate problem
You can modify your functions as follows:
function cacheUsers(result) {
return (users) ? users : users = extract(result);
}
and
model.getUsers = function () {
return (users) ? $q.when(users) : $http.get(URLS.FETCH, {cache: true}).then(cacheUsers);
};
It provides additional cache check after fetch and enables built-in cache for the object.
I suggest you to read http://www.webdeveasy.com/angularjs-data-model/