Working through a test app with a service and I keep getting an error about adding the service using the factory method. Not sure why, i know i am probably staring right at the problem..
The error i get is:
VM497 angular.js:10126 Error: [$injector:unpr] Unknown provider: githubProvider <- github
http://errors.angularjs.org/1.2.28/$injector/unpr?p0=githubProvider%20%3C-%20github
Thanks in advance.
(function() {
var github = function($http) {
var getUser = function(username) {
return $http.get('https://api.github.com/users/' + username).then(function(response) {
return response.data
});
};
var getRepos = function(user) {
return $http.get(user.repos_url).then(function(response) {
return response.data;
});
};
return {
getUser: getUser,
getRepos: getRepos
};
};
var module = angular.module("githubViewer");
module.factory('github', github) ;
});
Controller that injects the service
// Code goes here
(function() {
var app = angular.module("githubviewer", []);
var MainController = function(
$scope, github, $interval,
$log, $anchorScroll, $location) {
var onUserComplete = function(data) {
$scope.user = data;
github.getRepos($scope.user).then(onRepos, onError);
};
var onRepos = function(data){
$scope.repos = data;
$location.hash("userDetails");
$anchorScroll();
}
var onError = function(reason) {
$scope.error = "Could not fetch the Data";
};
var decrementCountDown = function(){
$scope.countdown -= 1;
if($scope.countdown < 1){
$scope.search($scope.username);
}
};
var countDownInterval = null;
var startCountDown = function(){
countDownInterval = $interval(decrementCountDown, 1000, $scope.countdown);
};
$scope.search = function(username){
$log.info("Searching for: " + username);
github.getUser(userName).then(onUserComplete, onError);
if (countDownInterval) {
$interval.cancel(countDownInterval);
}
};
$scope.username = "angular";
$scope.message = "GitHub Viewer";
$scope.repoSortOrder = "-stargazers_count";
$scope.countdown = 5;
startCountDown();
};
app.controller("MainController", MainController)
}());
You need to inject the service into app, from the code you posted. you are not injecting anything into the module.
var app = angular.module("githubviewer", ['yourservice', function(yourservice){}]);
This should get you headed in the right direction.
found my problem, the name of my module had a typo on capitalization. The V in Viewer was wrong.
Controller - var app = angular.module("githubviewer", []);
Service - var module = angular.module("githubViewer");
Related
I've moved this 'reports' feature from a single module (called 'aam') into the core, so that other modules (such as 'bbc') can use it.
Now I'm rewriting the unit test(s).
The grunt error I'm getting is
should go state aam.reports with URL_NOT_SPECIFIED
reports-state spec
TypeError: 'null' is not an object
(evaluating 'BbpcConfiguration.getProperty(configProperty).then')
which indicates to me that $state is empty or not structured correctly.
Here is the report controller:
(function() {
'use strict';
angular.module('com.ct.bbpcCore')
.controller('reportController', ['$window', '$state', 'BbpcUserService', 'BbpcConfiguration', function ($window, $state, BbpcUserService,BbpcConfiguration) {
angular.element(document).ready(function () {
//Get url base on locale
var reportUrl = "URL_NOT_SPECIFIED";
var currentState = $state.current.name;
var configProperty = "";
var title = "";
if (currentState.indexOf('aam.reports')) {
configProperty = 'report.aam.link';
title = "AAM.REPORT";
};
if (currentState.indexOf('bbc.reports')) {
configProperty = 'report.bbc.link';
title = "BBC.REPORT";
};
BbpcConfiguration.getProperty(configProperty).then(function(response) {
if (response) {
var language = BbpcUserService.getLanguageCd() || "en_CA";
reportUrl = response[language] || reportUrl;
}
var spec = "width=" + $window.outerWidth + ", height=" + $window.outerHeight;
$window.open(reportUrl, title, spec);
});
});
}]);
}());
And here is report-controller.spec:
describe('reports-state spec', function() {
'use strict';
var $injector, $window, $rootScope,
$state, BbpcConfiguration, reportController, $controller, BbpcUserService;
beforeEach(function() {
module('com.ct.bbpcCore', function($provide) {
$provide.value('BbpcConfiguration', BbpcConfiguration = {
getProperty: function(key){
if('report.aam.link' === key){
return {
"fr_CA": "https://eng-link",
"en_CA": "https://fre-link"
};
}
return null;
}
});
});
inject(function(_$injector_) {
$injector = _$injector_;
$window = $injector.get('$window');
$state = $injector.get('$state');
$rootScope = $injector.get('$rootScope');
$controller =$injector.get('$controller');
BbpcUserService =$injector.get('BbpcUserService');
});
});
it('should go state aam.reports with URL_NOT_SPECIFIED', function() {
$state.current = {'name': 'aam.reports' };
spyOn($window, 'open').andCallFake(function(){});
reportController = $controller('reportController', {'$window':$window, '$state':$state, 'BbpcUserService':BbpcUserService, 'reportLink':undefined});
$state.go('aam.reports');
$rootScope.$apply();
expect($state.current.name).toEqual('aam.reports');
expect($window.open).toHaveBeenCalledWith('URL_NOT_SPECIFIED', 'AAM.REPORT', 'width=0, height=0');
});
});
I tried simply adding the line $state.current = {'name': 'aam.reports' }; in the 'it' block, but that's not what it's looking for.
Not sure how to debug unit tests. :P I can't use a console.log($state) to peek into it.
I have a module with a service defined:
var ngError = angular.module('ngError', []);
ngError.service('ErrorService', ['$scope', function($scope) {
$scope.displayErrors = function(errors) {
alert(errors);
}
}]);
Then I have another module:
var ngLogin = angular.module('ngLogin', ['ngError']);
Which has a controller that attempts to use the first service defined on ngError:
ngLogin.controller('LoginCtrl', ['$scope', 'LoginService', 'ErrorService', function($scope, LoginService, ErrorService) {
$scope.user = {};
$scope.user.id = 0;
$scope.user.token = '';
$scope.login = function(callback) {
LoginService.login($scope.user.username, $scope.user.password, function(token) {
$scope.setToken(token);
$scope.$apply();
if (typeof callback === 'function') {
callback(callback);
}
}, function(errors) {
ErrorService.displayErrors(errors);
});
};
}]);
But some reason this is throwing the following error:
Unknown provider: $scopeProvider <- $scope <- ErrorService
You cannot use $scope within a service. Change the service as follows and it will work:
var ngError = angular.module('ngError', []);
ngError.service('ErrorService', [function() {
this.displayErrors = function(errors) {
alert(errors);
}
}]);
Try like this , working best for me
var app = angular.module('MyApp', []);
app.service('MyService', function () {
var property = 'First';
this.myFunc = function (x) {
return x*5;
}
});
//
controller 2 under second app module
var app = angular.module('AnotherApp',[]);
app.controller("AnotherAppCtrl", function($scope,MyService) {
$scope.value = MyService.myFunc(4);
});
I'm an angular newbie and I'm writing an Ionic app.
I finished my app and am trying to refactor my controller avoiding code repetition.
I have this piece of code that manages my modal:
angular.module('starter')
.controller('NewsCtrl', function($scope, content, $cordovaSocialSharing, $timeout, $sce, $ionicModal){
$scope.news = content;
content.getList('comments').then(function (comments) {
$scope.comments = comments;
});
$scope.addComment = function() {
};
$scope.shareAnywhere = function() {
$cordovaSocialSharing.share("Guarda questo articolo pubblicato da DDay", "Ti stanno segnalando questo articolo", content.thumbnail, "http://blog.nraboy.com");
};
$ionicModal.fromTemplateUrl('templates/comments.html', {
scope: $scope,
animation: 'slide-in-up'
}).then(function(modal) {
$scope.modal = modal;
});
$scope.showComment = function() {
$scope.modal.show();
};
// Triggered in the login modal to close it
$scope.closeComment = function() {
$scope.modal.hide();
};
$scope.$on('modal.shown', function() {
var footerBar;
var scroller;
var txtInput;
$timeout(function() {
footerBar = document.body.querySelector('#commentView .bar-footer');
scroller = document.body.querySelector('#commentView .scroll-content');
txtInput = angular.element(footerBar.querySelector('textarea'));
}, 0);
$scope.$on('taResize', function(e, ta) {
if (!ta) return;
var taHeight = ta[0].offsetHeight;
if (!footerBar) return;
var newFooterHeight = taHeight + 10;
newFooterHeight = (newFooterHeight > 44) ? newFooterHeight : 44;
footerBar.style.height = newFooterHeight + 'px';
scroller.style.bottom = newFooterHeight + 'px';
});
});
});
I have added this same code in 6 controllers.
Is there a way to avoid the repetition?
Probably what you are looking for is an angular service. This component is a singleton object, that you inject in every controller you need to execute this code.
Angular Services
Regards,
Below is an example of a service I created to retrieve address data from a Json file. Here is the working Plunk. http://plnkr.co/edit/RRPv2p4ryQgDEcFqRHHz?p=preview
angular.module('myApp')
.factory('addressService', addressService);
addressService.$inject = ['$q', '$timeout', '$http'];
function addressService($q, $timeout, $http) {
var addresses = [];
//console.log("Number of table entries is: " + orders.length);
var promise = $http.get('address.data.json');
promise.then(function(response) {
addresses = response.data;
// console.log("Number of table entries is now: " + orders.length);
});
return {
GetAddresses: getAddresses
};
function getAddresses() {
return $q(function(resolve, reject) {
$timeout(function() {
resolve(addresses);
}, 2000);
});
}
}
Here's an example of how I added dependencies for it and another service to my controller (This is NOT the only way to do dependency injection, but is my favorite way as it is easier to read). I then called my addressService.GetAddresses() from within my controller.
var app = angular.module('myApp', ['smart-table']);
app.controller('TableController', TableController);
TableController.$inject = [ "orderService", "addressService"];
function TableController( orderService, addressService) {
addressService.GetAddresses()
.then(function(results) {
me.addresses = results;
// console.log(me.addresses.length + " addresses");
},
function(error) {})
.finally(function() {
me.loadingAddresses = false;
});
});}
I also had to include my .js tag in a script element on my index.html.
<script src="addressdata.service.js"></script>
I created a factory that I would like to use in different pages:
var sessionApp = angular.module('sessionApp', ['LocalStorageModule']);
sessionApp.config(function(localStorageServiceProvider)
{
localStorageServiceProvider
.setPrefix('mystorage')
.setStorageType('localStorage');
});
sessionApp.factory('SessionFactory', function(localStorageService)
{
var service = {};
var _store = 'session';
service.load = function()
{
var session = localStorageService.get(_store);
}
service.save = function(data)
{
localStorageService.set(_store, JSON.stringify(data));
}
service.delete = function()
{
localStorageService.remove(_store);
}
return service;
});
Then I would add it on apps run method where I would assign it to the $rootScope. I left that part of the code commented out for now.
var loginApp = angular.module("loginApp", []);
loginApp.run(function($rootScope, SessionFactory)
{
//$rootScope.sessionFactory = SessionFactory;
$rootScope.$on('$routeChangeStart',
function(ev, next, current)
{
});
});
My error is:
Unknown provider: SessionFactoryProvider <- SessionFactory
Is it because my factory is from sessionApp and my login module is loginApp? Does that mean that I need to have the variables named the same like below:
File: login.js
var myApp = angular.module("loginApp", []);
myApp.run(function($rootScope, SessionFactory)
{
//$rootScope.sessionFactory = SessionFactory;
$rootScope.$on('$routeChangeStart',
function(ev, next, current)
{
});
});
File: session.js
myApp.config(function(localStorageServiceProvider)
{
localStorageServiceProvider
.setPrefix('mystorage')
.setStorageType('localStorage');
});
myApp.factory('SessionFactory', function(localStorageService)
{
var service = {};
var _store = 'session';
service.load = function()
{
var session = localStorageService.get(_store);
}
service.save = function(data)
{
localStorageService.set(_store, JSON.stringify(data));
}
service.delete = function()
{
localStorageService.remove(_store);
}
return service;
});
The array argument to angular.module is an array of other modules that you new module depends on. loginApp needs to list sessionApp as a dependency.
var loginApp = angular.module("loginApp", ["sessionApp"]);
I define a customer service named "greeting", but can't get the instance from $injector.get('greeting'). It will throw such error: Unknown provider: greetingProvider <- greeting. So which is the right way to get it? Following is the code:
var app = angular.module('myDI', []);
app.config(function($provide){
$provide.provider('greeting', function(){
this.$get = function(){
return function(name) {
console.log("Hello, " + name);
};
};
});
});
var injector = angular.injector();
var greeting = injector.get('greeting');
greeting('Ford Prefect');
You need to create the injector from the module.
var app = angular.module('myDI', []);
app.config(function($provide){
$provide.provider('greeting', function(){
this.$get = function(){
return function(name) {
console.log("Hello, " + name);
};
};
});
});
var injector = angular.injector(['myDI', 'ng']); //Add this line
var greeting = injector.get('greeting');
greeting('Ford Prefect');
var injector = angular.injector();
Try it here. FIDDLE