What's wrong with this factory dependencies issue? - javascript

I'm working with AngularJS.
I'd like to get a controller using a first factory which using another one.
It could be schematize like that:
MyCtrl -> Factory1 -> Factory2
So I tried to do in 3 different files (loaded in the following order):
Factory2.js
app.factory('Factory2', function () { ... })
Factory1.js
app.factory('Factory1',['Factory2', function (Factory2) { ... })
controller.js
app.controller('MyCtrl',['$scope', 'Factory1', function ($scope, Factory1) { ... })
And in my HTML I have:
<script src="services/factory2.js" type="text/javascript"></script>
<script src="services/factory1.js" type="text/javascript"></script>
<script src="controllers/controller.js" type="text/javascript"></script>
But it doesn't work and I've got this error Unknown provider: Factory2Provider <- Factory2 <- Factory1
What's wrong with my code? Am I missing something?

You can refactor your codes and use modules, in this way you will not need to use $inject
var app = angular.module('app', ['factories', 'mymodule']);
angular.module('factories', [])
.factory('Factory2', function () { })
.factory('Factory1', ['Factory2', function (Factory2) {
return myCustomFunction = function () {
alert('todo');
}
}]);
angular.module('mymodule', [])
.controller('MyCtrl', ['$scope', 'Factory1', function ($scope, Factory1) {
$scope.text = "testing";
}])
http://jsfiddle.net/kL78rdr3/3/

Why don't you use explicit injection with $inject? It is a better approach, because it gives you more control over the dependencies. For example:
userController.js
function userController (model, routeParams, searchService) {
//implementation
}
userController.$inject = ['$scope', '$routeParams', 'searchService'];
app.controller("userController", userController);
searchService.js
var searchService = function (http, log) {
//implementation
}
searchService.$inject = ["$http", "$log"];
app.factory("searchService", searchService);
This post may be useful: Explicit Dependency Injection

Related

Adding factory getting Error: [$injector:unpr]

Trying to add a simple factory and getting error:
Error: [$injector:unpr] http://errors.angularjs.org/1.4.6/$injector/unpr?p0=subfactoryProvider%20%3C-%20subfactory%20%3C-%20authService%20%3C-%20AuthorizationInterceptor%20%3C-%20%24http%20%3C-%20%24templateRequest%20%3C-%20%24compile
I have added a script tag:
<script src="app/subfactory.js"></script>
The subfactory is defined as follows:
(function () {
//'use strict';
angular
.module('app')
.factory('subfactory', subfactory);
function subfactory() {
var subValue = {};
return {
set: set,
get: get
};
function get() {
return subValue;
}
function set(value) {
subValue = value;
}
}
});
It is used in authService:
(function () {
//'use strict';
angular
.module('app')
.factory('authService', authService);
authService.$inject = ['subfactory'];
function authService(subfactory) {
// removed code for brevity
mgr.getUser().then(function (user) {
if (user) {
var idToken = user.id_token;
var dataIdToken = getDataFromToken(idToken);
subfactory.set(dataIdToken.sub);
} else {
//console.log("User not logged in");
}
});
I also have AuthorizationInterceptor that calls authService:
app.factory("AuthorizationInterceptor", ['$q', '$injector', '$rootScope', '$window', 'authService', function ($q, $injector, $rootScope, $window, authService) {
Please, How can I resolve this error?
Edit:
<script src="app/app.js"></script>
<script src="app/authService.js"></script>
<script src="app/subfactory.js"></script>
app.factory("AuthorizationInterceptor"... is defined in app.js
The error message is the only message in the F12 console.
Try flipping the order of your declaration files like follows :
// only define your module here
<script src="app/app.js"></script>
// define your factories
<script src="app/subfactory.js"></script>
<script src="app/authService.js"></script>
// define your authorization factory here just like the previous two
<script src="app/Authorization.js"></script>
Can not add it as comment. So adding an answer here. You need to change the order of file declaration . In your case error is because you have authService.js before subfactory.js. authService.js searches for its dependency and do not find it as subfactory.js yet not added.
<script src="app/app.js"></script>// If it main file whre angular module is created
<script src="app/subfactory.js"></script>
<script src="app/authService.js"></script>

Angular Error: $injector:unpr Unknown Provider when separating files

I have the following code and it works fine:
app.main.js:
angular.module('app', ['ngAnimate', 'ui.router'])
.factory('_', function() {
return window._;
});
angular.module('app').run(['$route', '$rootScope', '$location', function ($route, $rootScope, $location) {
var original = $location.path;
$location.path = function (path, reload) {
if (reload === false) {
var lastRoute = $route.current;
var un = $rootScope.$on('$locationChangeSuccess', function () {
$route.current = lastRoute;
un();
});
}
return original.apply($location, [path]);
};
}]);
bservice:
angular.module('app')
.service('bService', ['$http', '_', function($http, _) { ...
But when I try to separate de factory to a different file I get the Angular Error: $injector:unpr Unknown Provider. This file looks like this:
angular.module('app').factory('_', function() {
return window._;
});
I also made sure that the factory file is included.
Thanks
EDIT
Full error:
Unknown provider: _Provider
I use gulp for the file merges. So everything is in one file.
Gulp didn't like the name factorys. Because of this my factory became damaged in the main .js file.
The solution was to rename the folder to anything els then factorys.

Can't access function in Angular.js service

I am trying to create and use a new service in AngularJS, however,
I get the following error -
Error message
ProjectService.one is not a function
The Javascript -
var app = angular.module('app', ['ngRoute']);
app.service('ProjectService', function () {
this.one = function one() {
console.log('test service');
};
});
app.controller('ProjectsController', ['$scope', function (ProjectService, Test) {
ProjectService.one();
}]);
There is something wrong in your controller declaration. Your ProjectService parameter matches the $scope service. Do this instead;
app.controller('ProjectsController', ['$scope', 'ProjectService', 'Test', function ($scope, ProjectService, Test) {
ProjectService.one();
}]);
The service-parameters must match the array of services (same number and order)
You've to inject the ProjectService and other required dependent modules as mentioned below:
app.controller('ProjectsController', ['$scope','ProjectService','Test', function ($scope,ProjectService, Test) {
ProjectService.one();
}]);

Undefined variable passing data using service

I have declared my app and have one controller (for demonstration purposes):
var module = angular.module("app", [])
module.controller("modalCtrl", ["$scope", function ($scope, dataService) {
$scope.printEntity = function () {
console.log(dataService.getEntityArray());
}
}]);
And a service:
module.factory("dataService", function () {
var entityArrayService = [1,2];
return {
getEntityArray: function () {
return entityArrayService;
}
};
});
When I call $scope.printEntity from my view, I'm always told dataService.getEntityArray() is undefined.
I've loaded the service as a dependency and declared my entityArrayService array outside of my return statement. I've looked high and low for an answer but to no avail. My goal is to share a piece of data between two controllers, but at the minute I can't even use one controller to retrieve data.
The service isn't loaded as a dependency. Change this line:
module.controller("modalCtrl", ["$scope", function ($scope, dataService) {
to this:
module.controller("modalCtrl", ["$scope", "dataService", function ($scope, dataService) {
You are using strict syntax for dependencies declaration. So if you add a parameter to your controller, you must add its declaration too.
module.controller("modalCtrl", ["$scope", "dataService", function ($scope, dataService) {
...
}
You didn't inject dataService in your controller. Try with:
module.controller("modalCtrl", ["$scope", "dataService", function ($scope, dataService) {
// ...
});
The injection of the service in the controller is missing:
please correct to:
...
module.controller("modalCtrl", ["$scope", "dataService", function ($scope, dataService) {
...
The other code is correct.

Argument 'fn' is not a function got string

I have a part in my angular application on which I've binded a controller,
since then I got the Argument 'fn' is not a function Error, can anyone look at my code and explain why I got that Error?
I would be very gratefull :)
html-markup:
<section class="col-lg-12" data-ng-controller="MessageController">
<fieldset>
<legend>{{ 'MESSAGES' | translate }}</legend>
</fieldset>
<div class="margin-left-15">
<ul class="list-style-button">
<li data-ng-repeat="message in MSG">{{ message }}</li>
</ul>
</div>
</section>
controller:
(function() {
'use strict';
var controllers = angular.module('portal.controllers');
controllers.controller('MessageController', ['$scope', 'MessageService', '$rootScope', function MessageController($scope, MessageService, $rootScope) {
$rootScope.MSG = MessageService.getMessages();
$rootScope.$watch('MSG', function(newValue) {
$scope.MSG = newValue;
});
}]);
}());
Service:
(function() {
'use strict';
var messageServices = angular.module('portal.services');
messageServices.factory('MessageService', ['MessageData', 'localStorageService', 'UserService'], function(MessageData, localStorageService, UserService) {
return new MessageService(MessageData, localStorageService, UserService);
});
function MessageService(MessageData, localStorageService, UserService) {
this.messageData = MessageData;
this.localStorageService = localStorageService;
this.userService = UserService;
}
MessageService.prototype.getMessages = function() {
var locale = this.userService.getUserinfoLocale();
var messages = this.localStorageService.get(Constants.key_messages + locale);
if (messages !== null && messages !== undefined) {
return JSON.parse(messages);
} else {
return this.messageData.query({
locale: locale
}, $.proxy(function(data, locale) {
this.save(Constants.key_messages + locale, JSON.stringify(data));
}, this));
}
};
MessageService.prototype.save = function(key, value) {
this.localStorageService.add(key, value);
};
}());
data:
(function() {
'use strict';
var data = angular.module('portal.data');
data.factory('MessageData', function($resource) {
return $resource(Constants.url_messages, {}, {
query: {
method: 'GET',
params: {
locale: 'locale'
},
isArray: true
}
});
});
}());
order of js files in html head:
<script src="js/lib/jquery-1.10.js"></script>
<script src="js/lib/angular.js"></script>
<script src="js/lib/angular-resource.js"></script>
<script src="js/lib/angular-translate.js"></script>
<script src="js/lib/angular-localstorage.js"></script>
<script src="js/lib/jquery-cookies.js"></script>
<script src="js/lib/bootstrap.js"></script>
<script src="js/portal.js"></script>
The problem was in using the 'wrong' syntax to create the service
instead of using:
messageServices.factory('MessageService',
['MessageData','localStorageService', 'UserService'],
function(MessageData, localStorageService, UserService){
return new MessageService(MessageData, localStorageService, UserService);
}
);
I had to use:
messageServices.factory('MessageService',
['MessageData','localStorageService', 'UserService',
function(MessageData, localStorageService, UserService){
return new MessageService(MessageData, localStorageService, UserService);
}
]);
I closed the array with parameters to soon, and since I'm still learning I didn't see it directly, anyhow I hope I can help others who stumble upon this.
Today I got the same kind of error doing that silly mistake:
(function(){
angular
.module('mymodule')
.factory('myFactory', 'myFactory'); // <-- silly mistake
myFactory.$inject = ['myDeps'];
function myFactory(myDeps){
...
}
}());
instead of that:
(function(){
angular
.module('mymodule')
.factory('myFactory', myFactory); // <-- right way to write it
myFactory.$inject = ['myDeps'];
function myFactory(myDeps){
...
}
}());
In fact the string "myFactory" was brought into the injector who was waiting for a function and not a string.
That explained the [ng:areq] error.
The above answers helped me considerably in correcting the same issue I had in my application that arose from a different cause.
At built time, my client app is being concatenated and minified, so I'm writing my Angular specifically to avoid related issues. I define my config as follows
config.$inject = [];
function config() {
// config stuff
}
(I define a function, $inject it as a module and declare what it is).
And then I tried to register the config just as I registered other modules in my app (controllers, directives, etc..).
angular.module("app").config('config', config); // this is bad!
// for example, this is right
angular.module("app").factory('mainService', mainService);
This is wrong, and gave me the aforementioned error. So I changed to
angular.module("app").config(config);
And it worked.
I guess the angular devs intended config to have a singular instance and by so having Angular not accept a name when config is registered.
I had the same issue and In my case the problem was with angular-cookies.js file. It was in folder with other angularjs scripts and when I have used gulp to minify my js files the error occured.
Simple solution was just to place the angular-cookies.js file to another folder, outside the selected folder to minify js files.
My case
let app: any = angular.module("ngCartosServiceWorker"),
requires: any[] = [
"$log",
"$q",
"$rootScope",
"$window",
"ngCartosServiceWorker.registration",
PushNotification
];
app.service("ngCartosServiceWorker.PushNotification");
I forgot to add requires Array as parameters to service like this
app.service("ngCartosServiceWorker.PushNotification", requires);

Categories