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
Related
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!
});
We created dynamic module injection with requirejs in our angular application. Now we have created parameter instances of function for each module separately (commonModule, usersModule). How can we possible to make it dynamic for module dependency injection in requirejs and angularjs?
var _moduleFiles = ["common/module", "user/module"];
require(_moduleFiles, function(commonModule, usersModule) {
var app = angular.module('Myapp', [commonModule, usersModule]);
});
I have investigated about this issue and can found out that it may not be possible to implement dynamic module injection in requirejs.
Dynamic code loading (done in AMD systems via require([], function
(){})) is a basic requirement. CJS talked about it, had some
proposals, but it was not fully embraced. Node does not have any
support for this need, instead relying on the synchronous behavior of
require(''), which is not portable to the web.
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.
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
I am new to AngularJS (reading docs for a week or so) so bear with me :) I am trying to expose some 3rd party library (JayData) functionality to AngularJS controllers via the DI/service infrastructure.
Creating a service is a straightforward thing, as long as you can manage to create your own module for this, and set ng-app to that module.
var mod = angular.module('myModule', [], function ($provide) {
$provide.factory('$data', ['$scope', function (sc) {
return $data;
}]);
});
<html ng-app='myModule'></html>
In my case developers will create their own app/startup module, or will use the "default ng app" without specifying an kind of module names like <html ng-app="".
How can I register a service that is globally accessible like the built-in services like $scope or $http?
You can add components to the ng module, which is the default module, with angular.module("ng").service(...). As mentioned in the comments, this is a bad idea for several reasons, most prominently that the Angular team might provide a service with the same name later.
For reference, the preferred way is to define your own module such as myAwesomeDataModule and add it as a dependency in other modules: angular.module("myModule", ["myAwesomeDataModule"]).