I am trying to use $routeProvider dependency inside my controller:
.controller('mainController', function($scope, $state, $routeProvider) {
But I am getting the error:
Error: [$injector:unpr] Unknown provider: $routeProviderProvider <- $routeProvider
How do I know what dependencies I can inject into any given controller?
There are two phases inside angular
Configuration Phase (Here we use app.config to write a code)
Run phase (Where we use app.run, after run cycle all other directives gets executed using compile cycle)
Provider is nothing but service/factory but the most important thing is it can be accessible inside configuration phase.
Example
Suppose we have below provider
myApp.provider('unicornLauncher', function UnicornLauncherProvider() {
var useTinfoilShielding = false;
this.useTinfoilShielding = function(value) {
useTinfoilShielding = !!value;
};
this.$get = ["apiToken", function unicornLauncherFactory(apiToken) {
return new UnicornLauncher(apiToken, useTinfoilShielding);
}];
});
While inject it inside config you should always prefix it Provider like unicornLauncherProvider
While using it inside controller you could use it as unicornLauncher
Note:
Provider are always accessible inside .config(configuration)
phase with suffix Provider in their name, While inside controller you could > directly inject it using unicornLauncher (direct provider name)
Services/Factory They are not visible in config phase of angular
Still confuse then do refer this link
You can only access services in the controller not the providers so use $route here.
Therefore you are getting error $routeProviderProvider becuase it is looking for the provider for $routeProvider which is itself a provider for $route.
Docs
Related
I have problem to inject $rootScope in config angularJS, this is my code, but still error, maybe anyone help me how to inject $rootScope in config angularJS. .
thanks.
(function() {
'use strict';
angular
.module('uliappApp')
.directive('angular-loading-bar', ['cfpLoadingBarProvider'])
.config(cfpLoadingBarProvider);
cfpLoadingBarProvider.$inject = ['cfpLoadingBarProvider', '$rootScope'];
function cfpLoadingBarProvider(cfpLoadingBarProvider, $rootScope) {
cfpLoadingBarProvider.includeBackdrop = true;
console.log(rootScope.concessionLoadingScreen);
cfpLoadingBarProvider.spinnerTemplate = '<div class="loading-bar-container">'
+ '<div id="loading-bar-spinner"><div class="spinner-icon"></div></div></div>';
}
})();
You don't need rootScope in configuration phase, it can be simply achieved by using .run().
angular
.module('uliappApp')
.run(['$rootScope', function($rootScope){
$rootScope.concessionLoadingScreen = true;
}])
During the config phase, only providers can be injected.
Basically angularjs first invoke the config method and then invoke the run method. During config only providers are available. A provider can then be used to create service instance. So, you can use .run to inject $rootScope.
For example, the following is not allowed:
myMod.config(function(greeting) {
// WON'T WORK -- greeting is an *instance* of a service.
// Only providers for services can be injected in config blocks.
});
What you do have access to are any providers for services you've made:
myMod.config(function(greetingProvider) {
// ok fine!
});
All the best.
You can not use $rootScope during the configuration phase of an angular application.
Only constant and provider can be injected to the configuration phase.
You can use run phase, or create a provider (that is actually a service) to hold the configuration you want.
// Option 1 - during run
angular
.module('yourApp')
.run(['$rootScope', function($rootScope) {
}])
// Option 2 - provider
angular
.module('yourApp')
.provider('yourSettings', function() {
var $this = this;
this.yourSettings = 'yourValue';
this.$get = function() {
return $this;
}
})
angular
.module('yourApp')
.config(['yourSettingsProvider', function(yourSettingsProvider) {
// You can use yourSettingsProvider.yourSettings
}])
I want to dynamically inject a factory into my Angular controller based on the route parameter. This is my route configuration:
$routeProvider
.when("/tables/:table",
{
controller: "tableController",
templateUrl: "/app/views/table.html",
resolve: {
"factory": function r($route) {
return $injector.get($route.current.params.table + "Factory"); // Error!
}
}
})
For instance, when the route is tables/employee, I want an employeeFactory to be injected into tableController, and so on.
Unfortunately, this configuration does not work — I am getting an Unknown provider: employeeFactory error in the r function.
On the other hand, I can instead pass an $injector service directly to the tableController and successfully resolve employeeFactory there:
(function (angular) {
var tableController = function ($routeParams, $injector) {
// employeeFactory resolves successfully here!
var factory = $injector.get($routeParams.table + "Factory");
};
angular.module("appModule").controller("tableController", tableController);
})(angular);
However, I do not like this approach because it follows the service locator anti-pattern. I would really like factory to be injected using routing configuration and not this ugly workaround.
So, why Angular is throwing an error when using $injector.get() with resolve, but successfully resolves the factory inside of the tableController? I am using Angular 1.4.4.
You apparently use $injector that was injected into config block, and it differs from $injector that is injected anywhere else. The former acts on service providers, the latter acts on service instances.
It should be
"factory": function r($route, $injector) {
return $injector.get($route.current.params.table + "Factory");
}
I am kind of new to the AngularJS framework and I am trying to migrate my test project using the standard router to use the UI-router, but I get the following error:
Error: [ng:areq] Argument 'mainCtrl' is not a function, got undefined
What I have done so far is:
Controller:
// mainCtrl.js
angular.module("sm-web")
.controller('mainCtrl',['$scope',
function($scope) {
...
}]);
Router:
angular.module('sm-web', ['ui.router'])
.config(['$stateProvider', '$urlRouterProvider', function( $stateProvider, $urlRouterProvider ) {
$urlRouterProvider.otherwise('root');
$stateProvider
.state('root', {
url: '',
templateUrl: path + 'ng/sm/view/main.html',
controller: 'mainCtrl'
});
}]);
Index:
<body ng-controller="mainCtrl">
<main-menu></main-menu>
<div class="container">
<div ui-view></div>
</div>
</body>
This works when I use the standard router, but not with the UI-router. Does anyone have any idea of what I am doing wrong?
It seems you have an issue w/the order you declare things. For you to declare the module "sm-web" you need to do this:
angular.module('sm-web', ['ui.router']);
Note that the presence of that 2nd array argument is what tells Angular that you're declaring the module (eg. creating a new module). When you leave that 2nd argument out, you're retrieving the module you previously declared.
So with that in mind, look at how it all is coming together in your code:
To declare the controller, you retrieve the module "sm-web" (by leaving off the 2nd array arg).
When configuring the router states, you declare a new module "sm-web". But note that immediately after you declare this new module, you try to register a state with the controller named "mainCtrl" -- but that doesn't exist yet.
You need to create the module somewhere before doing all of the above. After creating the module, then register the controller on the module. Finally, with the controller defined, then you can register the state that uses the controller.
There's too many ways to solve this ordering problem, so I'm not going to suggest anything further. It depends on what files the code lives in and the order you load those files in index.html.
In order to avoid your problem change your code by the following code:
// mainCtrl.js
angular.module("sm-web")
.controller('mainCtrl',['$scope',
function($scope) {
...
}]);
I have a provider config which uses $state.go to jump to states. When I use $state as a function parameter it works, but when I try to modify the function parameters to support minification such as
.provider('Navigation',["$stateProvider","$state",function($stateProvider,$state)
then I get the following resolve dependency error :
Uncaught Error: [$injector:modulerr] Failed to instantiate module apfPrototypeJs due to:
Error: [$injector:unpr] Unknown provider: $state
How to circumvent this problem?
You can only inject providers in a provider because no services are instantiated at that point yet and also because the provider methods are used especially for configuration, they can only be accessed during the config phase of the app, it does not make sense to have the ability to inject any services. But You can inject any service (not provider) in the provider's constructor function defined via $get property.
i.e
.provider('Navigation',["$stateProvider",function($stateProvider) { //Inject provider here
this.$get = ["$state", function($state){ //Inject $state here
console.log($state)
}]
}]);
As an alternate syntax (using $inject to support minification) you could do:-
.provider('Navigation', function(){
this.$get = navigationService;
navigationService.$inject = ['$state'];
function navigationService($state) {
console.log($state)
}
}]);
Here is a working example of how I have set up an interceptor which attaches an authentication token to each request (this is more or less the example from https://docs.angularjs.org/api/ng/service/$http)
angular.module("app", [])
.config(function ($httpProvider) {
$httpProvider.interceptors.push("authInterceptor");
})
.factory("authInterceptor", function ($q) {
return {
// interceptor configuration here
}
})
I have a lot of other stuff in my config and run blocks which call and initiate services from different angular modules, so I want to tidy things up a bit. However I understand there are some very specific rules to dependency injection in config blocks, which I don't quite understand, and these are preventing me from defining my authInterceptor factory in a separate module. As other logic in the config and run blocks calls other modules in the app, declaring that interceptor right there looks out of place.
This is what I want to do:
angular.module("services.authInterceptor", [])
.factory("authInterceptor", function ($q) {
return {
// interceptor configuration here
}
});
angular.module("app", [
"services.authInterceptor"
]).config(function ($httpProvider, authInterceptor) {
$httpProvider.interceptors.push("authInterceptor");
});
// Error: Unknown provider authInterceptor.
I tried injecting it to the run block instead, but I guess you're not allowed to inject $httpProvider there:
angular.module("app", [
"services.authInterceptor"
]).run(function ($httpProvider, authInterceptor) {
$httpProvider.interceptors.push("authInterceptor");
});
// Error: Unknown provider: $httpProviderProvider <- $httpProvider
Where should I inject the module so that $httpProvider is also injectable, and where should I add the interceptor to existing ones? My main goal is keeping the interceptor and other similar services in their own self-containing modules.
EDIT
I get a different error which seems to be getting me closer when I declare a provider instead of factory (for some reason I always thought these were interchangeable):
angular.module("services.authInterceptor")
.provider("authInterceptor", function ($q) {
return {}
})
// Error: Unknown provider: $q
So it now successfully injects authInterceptor to my config block, but fails when trying to find $q.
During the configuration phase only providers and constants can be injected. This is to prevent instantiation of services before they have been fully configured.
This is why you register interceptors by name (pushing the name as a string into the $httpProvider.interceptors array). They will be resolved later during runtime.
This is exactly what you did in your working example, and what you need to do in your second, even when the interceptor is in another module:
angular.module("services.authInterceptor", [])
.factory("authInterceptor", function ($q) {
return {
// interceptor configuration here
}
});
angular.module("app", ["services.authInterceptor"])
.config(function ($httpProvider) {
$httpProvider.interceptors.push('authInterceptor');
});
Demo: http://plnkr.co/edit/A8SgJ87GOBk6mpXsoFuZ?p=preview