How do I access the $locationProvider to configure it? - angularjs

What is the correct way to get the $locationProvider configuration parameters from a service / controller ? When doing a simple dependency injection with function ( $locationProvider ), I get the following error :
Unknown Provider : $locationProviderProvider <- $locationProvider <- myCtrl

I also got this error.
You're allowed to inject a $location into a controller, but not a $locationProvider.
Instead, the $locationProvider can be injected into a config method:
var app = angular.module("myApp", []);
app.config(function($locationProvider) {
$locationProvider.html5Mode(true);
});
app.controller("myCtrl", function($location) {
$location.path("/some/path");
});
And since I made this additional mistake: it's not just that you should add an app.config bit, but also remember to remove $locationProvider from the controller arguments, or you'll keep getting this error.
If I understand things correctly, provider configuration happens during the configuration phase of the app lifecycle, as opposed to the run phase. Thus this separation. You can read a bit more about these phases here.
I suspect that the reason for the error message is that when you inject $foo into a controller, it looks for a $fooProvider. Thus when we injected a $locationProvider, it looked for a $locationProviderProvider.

Related

reset myApp into body by angular.bootstrap

I have a problem.
I wants design multiple modules, each module will config route for itself. And before login I just wants load 3 modules (with 3 route), and after login I continue load 3 module (with 3 route). So I need re-config myApp to add new routes, then re-set into body to apply myApp.
And my solution is:
I create mainModule is myApp, and i config for it then I set into body by angular.bootstrap
angular.element(document).ready(function() {
angular.bootstrap(document.body, ["myApp"]);
});
Then, I need re-config for myApp and I set again.
angular.element(document).ready(function() {
angular.bootstrap(document.body, ["myApp"], true);
});
An error occurs
[ng:btstrpd] App Already Bootstrapped with this Element '<body cz-shortcut-listen="true" class="ng-scope">'(…)
How can I reset myApp into body or any solution ???
Thanks,
While lazy loading is not among listed features in Angular, some of the things which are intrinsic to config phase can be performed at run-time (while they cannot be recommended and belong to 'use at your own risk' category).
When provider is being used to configure the service before its instantiation, most likely (it depends on service implementation) it can be used to configure it after it was instantiated, e.g.
app.config(function ($routeProvider, $provide) {
// now $routeProvider is available for injection during both config and run phases
$provide.constant('$routeProvider', $routeProvider);
});
app.run(function ($routeProvider, $location) {
$routeProvider.when('/brand-new-route', { ... });
$location.path('/brand-new-route');
});
More of this injector trick here.
This method isn't forbidden but relies on current service implementation and undocumented behaviour, so it has to be either tested thoroughly or should be avoided at all.

How to inject '$urlRouterProvider' into factory?

I have followed this post How inject $stateProvider in angular application? and I have managed to figure out how to use '$stateprovider' but now I have issue with the '$urlRouterProvider'.
Does that mean I can't inject '$urlRouterProvider' into controller either and it should be only injected into config?
I highly appreciate any help any help on this issue.
There is a very narrowed snippet of the $urlRouterProvider code:
$UrlRouterProvider.$inject = ['$locationProvider', '$urlMatcherFactoryProvider'];
function $UrlRouterProvider( $locationProvider, $urlMatcherFactory) {
// I. config
// these are CONFIGURATION methods
// we can access in .config() phase
....
this.rule = function (rule) {
...
}
...
this.when = function (what, handler) {
...
}
...
// II. application run
// this is the service/factory/configured provider
// injected in the .run() phase via IoC
this.$get = $get;
$get.$inject = ['$location', '$rootScope', '$injector', '$browser'];
function $get( $location, $rootScope, $injector, $browser) {
...
return {
sync: function() {
...
},
listen: function() {
...
}
And this is the answer. In the config we do have access to configuration methods of the provider $urlRouterProvider. While later, in phase of application run, our services/factories are via IoC provided with the result of the configured $get()
For more details, see:
Configuring Providers
You may be wondering why anyone would bother to set up a full-fledged provider with the provide method if factory, value, etc. are so much easier. The answer is that providers allow a lot of configuration. We've already mentioned that when you create a service via the provider (or any of the shortcuts Angular gives you), you create a new provider that defines how that service is constructed. What I didn't mention is that these providers can be injected into config sections of your application so you can interact with them!
First, Angular runs your application in two-phases--the config and run phases. The config phase, as we've seen, is where you can set up any providers as necessary. This is also where directives, controllers, filters, and the like get set up. The run phase, as you might guess, is where Angular actually compiles your DOM and starts up your app.
In case, you need to access $stateProvider or $routeProvider configuration even later... there is a way... Check this plunker. Can hardly say that this is the angular way... but it is working. Check it here
AngularJS - UI-router - How to configure dynamic views
http://plnkr.co/edit/I4AGHa3xgfv8WUMotxNL?p=preview

How can I retrieve the injector for my application?

I'm trying to run a function and have services injected into it. I thought this could easily be accomplished using $injector. So I tried the following (simplified example):
angular.injector().invoke( [ "$q", function( $q ) { $q.something(); } ] );
Which results in Uncaught Error: [$injector:unpr] Unknown provider: $qProvider <- $q.
I know I can solve that by using angular.injector( ["ng"] ) instead, but there are actually several more dependencies.
It would be perfectly fine, if I could just retrieve the injector instance that is used everywhere else in my application.
The documentation for angular.injector suggests that you can retrieve it with angular.element(document).injector(), but that results in undefined for me.
You shouldn't be needing this, but you can get your app's $injector using the root-element of your app (or any child element).
E.g., if you use ngApp on the body:
angular.element(document.body).injector();
ExpertSystem's answer worked perfectly for me
This works perfectly for me. I'm trying to invoke a function from an angular service outside the angular scope in the document "resume" event for use in my cordova application. Here is the code that I used
var injector = angular.element(document.body).injector(); //get the document
injector.invoke(['myService', function (myService) {
myService.doSomething();
}]);
Try this:
var $injector = angular.injector(['myApp','ng'])
For $location you need to bootstrap the app to the page (start the app):
var $injector = angular.bootstrap(document, ['myApp'])
This will return the injector every time you call it but won't create any conflicts if the script was already loaded.

AngularJS: unknown provider until after page loads?

So this is really weird, maybe it has a simple answer I'm missing. The following code gives an unknown provider error:
var foo = angular.module('foo', [ 'ngRoute', 'ngAnimate', 'ngCookies' ]);
foo.factory('fooApi', function ($scope, $http) {
var url = '/api/';
var factory = {};
factory.action = function (fields) {
fields.userid = $scope.userid;
fields.token = $scope.token;
console.log(JSON.stringify(fields));
return $http.post(url, { data: fields });
};
return factory;
})
.controller('loginController', function ($scope, fooApi) {
// do stuff
});
It's all loading together in the same file, and I'd think the factory being first would resolve and the injector would be able to find it when referenced below. But it gives an unknown provider error.
However, if I comment out the controller and wait for the page to load and then do the exact same controller declaration in the Chrome JS console it works fine.
Anyone run into this before and know how to deal with it? I haven't been able to find this same exact issue anywhere.
Like #tasseKATT said, you can not inject $scope into a service, particularly a factory. Maybe your confusion is because $scope can be injected in controllers, so you tried to injected into a factory.
An interesting thing is that the $scope that you see being injected into controllers is not a service - like the rest of the injectable stuff -, but is a Scope object.
The main purpose of $scope is a king of glue between views and controllers, it doesn't make much sense to pass a $scope into a service.
The services only have access to the $rootScope service.
If you need to pass the $scope of a specific controller to a service always you can pass it like parameter of a function in the service. This approach is not recommended because starting to break the SoC and the single responsibility principle, but maybe could fit you.
Good luck :-)

Accessing $location from injector

I have a simple angularjs application with a single router at the moment :
angular.module('myApp', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/editFilter/:id', {templateUrl: '/webapp/template/filterDetail'});
}])
My goal is to call the editFilter template when I need it.
I am trying to retrieve the $location like that :
angular.injector(['myApp']).get('$location')
but it fails with
Error: [$injector:unpr]
http://errors.angularjs.org/1.2.1/$injector/unpr?p0=%24rootElementProvider%20%3C-%20%24rootElement%20%3C-%20%24location%20%3C-%20%24route
If I call angular.injector(['myApp']).get('$location') it returns true.
Any idea of what I am doing wrong? I have try several workaround but everytime I end up with a very similar error.
If you would have read the error page you see that you forgot to include certain dependencies. Please don't forget to include them. The one failing now is $rootElement, as you can read in the error. Include this one, and try again to see if other dependencies should be included.
EDIT:
OK, I was wrong, after some reading I noticed that this method:
angular.injector(['myApp']).get('$location')
creates a new injector instance. This is not what you want I think.
So I don't know what is your case but if you are in AngularJS just inject the $injector instance. If not in AngularJS call
$injector = angular.element([DOM element]).injector();
$injector.get('$location');

Resources