difference between calling angular.injector with and without ['ng'] - angularjs

Documentation for angular.injector says that 'ng' module must be added as a dependency here: https://docs.angularjs.org/api/ng/function/angular.injector but documentation of $injector shows an example as shown below:
var $injector = angular.injector();
here: https://docs.angularjs.org/api/auto/service/$injector
What is the difference in the two approaches ?

angular.bootstrap adds ng module by default and calls angular.injector internally. angular.injector doesn't add ng module.
angular.injector() results in an injector where core Angular services are unavailable. When being used without ng module it is a generic DI container.

Related

AngularJS: injecting a dependency to the main module or to a controller?

I'm confused about something. Some dependencies have to be injected to the main module. For example:
angular.module("app", ["ui.router", "ui.bootstrap", "toaster"]);
Whereas some other dependencies can just be injected into the controllers, but don't need to be injected into the main module. For example:
angular.module("app").controller("newCtrl", ["$q", newCtrl);
I'm having difficulties understanding why. Any help will be much appreciated.
$q a service within the core ng module, per the documentation.
All services within the ng module are bootstrapped and registered when the angular.js file is loaded and parsed. This allows you to inject them anywhere in your app.
However, the three examples you have listed above are all external, modular dependencies. They need to be explicitly registered into your application so that the components within are available when the $injector service attempts to resolve them.
You inject modules into other modules.
You inject providers, services, and factories that are included in those modules into the specific controllers.
In Angular, you define a module like so:
angular.module('MyModule1', []);
Notice how module function takes two arguments. Second argument being the array of other modules this module is dependent on. This construct is for setting a module.
Once the module is defined, you can attach controller, services etc. to the module.
angular
.module('MyModule1')
.service('MyService1');
Notice, how this time only one argument was give to the module function. That means you are getting an already registered module.
Lets say you create another module MyModule2, but MyModule2 needs to use the services defined by the MyModule1.
You just set the module MyModule2 with MyModule1 as its dependency.
angular.module('MyModule2', ['MyModule1']);
Now, you want to create a controller (or a directive, or a service, whatever) in MyModule2 that actually makes use of the service MyService1 defined in MyModule1.
That's where the Dependency Injection (DI) of Angular comes in. You define your controller with the service name as function parameter and when Angular instantiates your controller, it makes sure the service instance is found and provided to your controller.
angular
.module('MyModule2')
.controller('MyController2', function (myService1) {
// Hey I can use myService1
// Dependency Injection FTW!
});

Unknown provider: ngTagsInputProvider <- ngTagsInput

I injected the 2.1.1 version ngtagsinput like this into my controller:
app.controller('homeCtrl', ['$scope','$http','ngTagsInput', function($scope,$http){
}])
*NOTE: TESTED! add ngTagsInput into the function() will not make a difference...
I loaded the ngtagsinput lib after angularjs lib.
I wonder what else I could test to resolve the error of:
Error: [$injector:unpr] Unknown provider: ngTagsInputProvider <- ngTagsInput
http://errors.angularjs.org/1.2.9/$injector/unpr?p0=ngTagsInputProvider%20%3C-%20ngTagsInput
Don't get me wrong, I know basically this provider is not detected.
but my lib is found (did not report 404), I saw ngTagsInput used in its library....
So, its really bugging me the same solution no more works for this lib! What's special about this lib and why this error is there while I met all the standard to fix it?
It looks like you have tried to inject ngTagsInput into your controller, while you should be injecting it into your module as a dependency. For example:
angular.module('myApp', ['ngTagsInput'])
note module, not controller
You can see as per the creators example: https://github.com/mbenford/ngTagsInput#example
This happens because there are multiple types of injection used in angular. When you declare a module, you need to specify which other modules are available to use within your module.
See: https://docs.angularjs.org/guide/module
When you inject into say a controller, you are basically saying that you want to use a particular object inside it. That object must be a part of your module to be valid. For a third party library, this usually means adding it as a module dependency (as above), and then injecting any object that is part of that library into your controllers and services.

AngularJS - AUTO module and $injector

On this page, the Angular docs describe the AUTO module as:
Implicit module which gets automatically added to each $injector.
Yet, the $injector is located inside this AUTO module.
AUTO
$injector
AUTO
$injector ...
Clearly I'm missing something.
How does the AUTO module relate to the angular.module(), and where does the $injector fit in?
angular.module()
AUTO
$injector
This would make sense, but then the docs that imply that AUTO is added to $injector doesn't make sense. I'm wondering if I'm misinterpreting something. So my question is, am I misinterpreting something?
AUTO basically wires up modules with $provide and $injector. The $injector references itself so $injector === $injector.get('$injector'). It avoids the chicken/egg scenario by building up the module outside of the Angular context and manually shoving the $injector and $provide into it. From that point forward the module can then use $provide, $injector, etc. You will never reference a module explicitly called "AUTO" but any module you create via angular.module will have an $injector and $provide. The other services come from the 'ng' module but the AUTO portion of it has to be built up so there is a DI container to use.
There are two injectors, an internal one, and an external one:
The instanceInjector stores the list of instantiated services in the system. It is initialized with an empty object. The providerInjector maintains the list of uninstantiated services.
The angular.injector method can create an instance:
angular.injector().get("$injector")
The built-in module ng can also:
angular.module("ng")._configBlocks[0][0]
References
Studying the Angular injector - the twin injectors
Deconstructing AngularJS Injector
AngularJS Error Reference: $injector - cdep
AngularJS source: injectorSpec.js

Importance of order in registering provider and configuring a module in angular.js

it seems that from angular's point of view the order of registering of a service provider and the module configuration code is important: in order for the configuration code to find the provider, the provider should be registered before.
This was a total surprise for me, as I thought that angular first processes all provider registrations, to make them available for DI, and then calls config callbacks, like this:
module.config(function(myServiceProvider) {...});
Please see here a very short test that demonstrates the problem. It fails on "unknown provider", you can see it in the JS console: http://plnkr.co/edit/jGJmE2Fq7wOrwubdlTTX
Am I missing anything here? Is it an expected angular behavior?
Thanks.
Looks like this behavior has changed in more recent versions of Angular (not sure when exactly). I modified your Plunker to point from 1.0.7 to 1.3.0 and it worked without error as you had originally expected.
Similar example of code that works:
var myModule = angular.module('myModule', []);
myModule.config((myServiceProvider) => {
});
myModule.service('myService', () => {
});
Running a config for a provider before the provider is registered with the module should work just fine as you were expecting.
Reference
For reference, this reported issue appears to be the one to have fixed it: https://github.com/angular/angular.js/issues/6723
The Angular documentation for module state that:
Recommended Setup
While the example above is simple, it will not scale to large applications. Instead we recommend that you break your
application to multiple modules like this:
A service module, for service declaration
A directive module, for directive declaration
A filter module, for filter declaration
And an application level module which depends on the above modules, and which has initialization code.
As you are using a single module that you call app, you are creating a dependency between that module's config and declaration of a provider. What you should have done is to place all your providers into a separate module, such as:
var appr = angular.module('appr', [])
.provider('myService', function() {
this.$get = function() {};
})
Then you declare the dependency of your app using:
var app = angular.module('plunker', ['appr']);
Check out the updated Plunker: http://plnkr.co/edit/Ym3Nlsm1nX4wPaiuVQ3Y?p=preview
Also, instead of using the generic provider, consider using more specific implementation of provider such as controller, factory or service. Take a look at Module API documentation for more detail.

AngularJS - please explain the line

What exactly does the "inject" line do?:
function PhotoGalleryCtrl($route, $xhr) {
}
PhotoGalleryCtrl.$inject = ['$route', '$xhr'];
Are $route and $xhr predefined somewhere? Where to read about them?
Who said that the PhotoGalleryCtrl function has the .$inject method?
Both $route and $xhr are native AngularJS services, the latter has been replaced by $http in the most recent versions of AngularJS. They are part of the ng module.
You can read about them here
ng.$route
ng.$http
$inject tells angular to make available those services to the controller PhotoGalleryCtrl
Dependency injection and modules are core features of Angular. They both minimize global state and allow for better unit testing, you can read more about them here
Modules
Dependency Injection

Resources