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

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.

Related

Unknown Provider in AngularJS $resource

I am getting the infamous unknown provider error, and looked into every potential answer up here but I think that I am missing something:
app.js
var myApp = angular.module('myApp', [
'ngResource',
'myAppControllers',
'myAppServices',
'myAppFilters'
]).config([
'$locationProvider',
function(
$locationProvider) {
$locationProvider.html5Mode({
enabled: true,
requireBase: false,
rewriteLinks: false
});
}]);
var myAppControllers = angular.module('myAppControllers', []);
var myAppServices = angular.module('myAppServices', []);
var myAppFilters = angular.module('myAppFilters', []);
Item.js
myAppServices.factory('Item',
function($resource) {
return $resource('/api/items/:id');
});
ItemService.js (1)
myAppServices.factory('itemService',
function($q,
$http,
Item) {
return {
delete: function(id){
// Item, $q and $http are undefined here
return Item.delete({id: id}).$promise;
}
};
});
alternative ItemService.js (2)
myAppServices.factory('itemService', [
'$q',
'$http',
'Item', // If I don't inject it here I can use this service with $q and $http
function($q,
$http,
Item) {
return {
delete: function(id){
return Item.delete(id).$promise;
}
};
}]);
And in my controller:
myAppControllers.controller('ItemsCtrl', [
'$scope',
'itemService',
function(
$scope,
itemService) {
var ctrl = this;
ctrl.ItemService = ItemService;
ctrl.deleteItem = function(id){
ctrl.itemService.delete(id)
.then(function(response){
console.log(response);
}, function (error) {
console.log(error);
});
};
}]);
So if I try like in (1), I am getting undefined.delete is not a function in itemService.
If I try as in (2), the app fails to load with:
Unknown provider: ItemProvider <- Item <- itemService
So what am I doing wrong?
You have multiple issues here.
You need to have myAppServices as a dependency of myAppControllers in order to use it in a controller.
So, following should be how you do it:
var myAppServices = angular.module('myAppServices', []);
var myAppControllers = angular.module('myAppControllers', ['myAppServices']);
In myAppServices module you have Item service which uses $resource but you haven't injected ngResource as a dependency of myAppServices.
Here's your code in plunker without errors
EDIT: Also make sure all your files are included in index.html properly!
i think in $resource ur are missing argument it should look like
$resource('/api/items/:id', {id:'#id'});
Try (1) again , undefined is because of this
and also ur delete should be look like this
return Item.delete({id : id}).$promise;

Factory Service unable to load json file

I have a JSON file, data.json, in the same folder as the file below. When I run this however it's returning not found.
I have also tried putting the $http.get request in a factory, but same result - not found. I also tried changing the .json extension to .txt as was suggested elsewhere, but this also didn't work.
The rest of the code came with the angular seeds project.
Is there something i'm missing in the other files or some other trick to the get request?
'use strict';
var myApp = angular.module('myApp.view1', ['ngRoute']);
myApp.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/view1', {
templateUrl: 'view1/view1.html',
controller: 'View1Ctrl'
});
}]);
myApp.controller('View1Ctrl', [
'$scope',
'$http',
function($scope, $http) {
$http.get('data.json')
.then(function(res){
$scope.quiz = res.data
});
}]);
Here is the plnkr: https://plnkr.co/edit/Lf6QcyKSn4DsQrgJhUq6?p=preview
'use strict';
var app=angular.module('myApp.view1', [])
app.factory('mainInfo',
function($http) {
var obj={};
obj.method =function(){
return $http.get('tag.json')
}
return obj;
})
app.controller('View1Ctrl', [
'$scope',
'$http',
'mainInfo',
function($scope, $http, mainInfo) {
mainInfo.method().success(function(response) {
$scope.myWelcome = response;
debugger
});
}]);
Try placing the .json file in the same folder where the js is present.
The .json file must not be in the same folder as the js file. Relative paths are resolved relative to the including index.html file. If you have this structure:
+-index.html
|-folder
| \-data.json
\-js
\-app.js
You have to $http.get("folder/data.json") in app.js to make it work.

What's wrong with this factory dependencies issue?

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

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);

Angular.js - error with providerInjector

I have a problem with providers in angular, I get this error:
Row 2696: Error: Unknown provider: a
Using unminified angular v 1.06, Row 2696:
providerInjector = createInternalInjector(providerCache, function() {
throw Error("Unknown provider: " + path.join(' <- '));
}),
This is the code:
var myApp = angular.module('myApp', [], function ($interpolateProvider) {
$interpolateProvider.startSymbol('{[{');
$interpolateProvider.endSymbol('}]}');
});
myApp.directive('buttonsRadio', function() {
[...]
});
myApp.controller('MainController', function MainController ($scope) {
[...]
})
Any ideas?
Edit: Added error message:
Error: Unknown provider: aProvider <- a
createInjector/providerInjector<#/libs/angular.js:2696
getService#/libs/angular.js:2824
createInjector/instanceCache.$injector<#/libs/angular.js:2701
getService#/libs/angular.js:2824
invoke#/libs/angular.js:2842
instantiate#/libs/angular.js:2874
#/libs/angular.js:4759
applyDirectivesToNode/nodeLinkFn/<#/libs/angular.js:4338
forEach#/libs/angular.js:138
nodeLinkFn#/libs/angular.js:4323
compositeLinkFn#/libs/angular.js:3969
compositeLinkFn#/libs/angular.js:3972
nodeLinkFn#/libs/angular.js:4354
compositeLinkFn#/libs/angular.js:3969
publicLinkFn#/libs/angular.js:3874
bootstrap/resumeBootstrapInternal/</<#/libs/angular.js:963
Scope.prototype.$eval#/libs/angular.js:8011
Scope.prototype.$apply#/libs/angular.js:8091
bootstrap/resumeBootstrapInternal/<#/libs/angular.js:961
invoke#/libs/angular.js:2857
bootstrap/resumeBootstrapInternal#/libs/angular.js:960
bootstrap#/libs/angular.js:973
angularInit#/libs/angular.js:934
#/libs/angular.js:14756
f.Callbacks/n#http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js:2
f.Callbacks/o.fireWith#http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js:2
.ready#http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js:2
B#http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js:2
/libs/angular.js
Line 5704
Before running uglify or any other ofuscator/compression algorithm, you should run the grunt task ng-annotate which adds the dependencies as strings for you as an injectable array, this makes your code a lot cleaner as the injectable annotaion can be added automatically as a build step rather than having to manually code it.
myApp.controller('MainController', function MainController ($scope) {
[...]
})
Becomes:
myApp.controller('MainController', ['$scope', function MainController ($scope) {
[...]
}])
Take a look at: https://github.com/olov/ng-annotate
Update:
ng-min AngularJS Pre-minifier deprecated –> use ng-annotate
I assume you're using some kind of javascript obufuscator (Clousure, SquishIt, UglifyJS etc).
In this case you need to specify dependencies in such way:
var myApp = angular.module('myApp', [], ['$interpolateProvider',function ($interpolateProvider) {
$interpolateProvider.startSymbol('{[{');
$interpolateProvider.endSymbol('}]}');
}]);
myApp.directive('buttonsRadio', function() {
[...]
});
myApp.controller('MainController',['$scope', function MainController ($scope) {
[...]
}])
Note to specify dependenices for dependency injection - instead of passing function, you need to specify array with list of strings with names of objects to inject into parameters and the function itself.

Categories