In AngularJS, dependency injection (DI) is a core feature that allows components (controllers, services, factories, etc.) to declare dependencies that Angular automatically injects. However, sometimes you may need to inject dependencies dynamically based on runtime conditions. This is where AngularJS’s $injector
, $provide
, and manual annotation techniques come in handy.
1. Using $injector
to Inject Dependencies at Runtime
The $injector
service in AngularJS allows you to manually retrieve and inject dependencies dynamically.
Example: Dynamically Injecting a Service
app.controller('DynamicController', function($scope, $injector) {
// Dynamically injecting the $http service
var $http = $injector.get('$http');
// Fetch data using dynamically injected service
$http.get('/api/data').then(function(response) {
$scope.data = response.data;
});
});
How It Works?
$injector.get('serviceName')
retrieves any registered AngularJS service at runtime.- This is useful when you need conditional dependency injection (e.g., injecting a service only when needed).
Use $injector.get()
when you need to inject services dynamically based on conditions.
2. Using $provide
to Register Dependencies Dynamically
If you need to register a dependency dynamically, AngularJS’s $provide
service allows you to define services, factories, and constants dynamically.
Example: Defining a Service Dynamically
var app = angular.module('myApp', []);
app.config(function($provide) {
$provide.service('DynamicService', function() {
this.getMessage = function() {
return "This service was registered dynamically!";
};
});
});
app.controller('MainController', function($scope, DynamicService) {
$scope.message = DynamicService.getMessage();
});
How It Works?
$provide.service('DynamicService', function() {...})
dynamically registers a new service.- The service can then be injected into controllers or other components.
Use $provide
when you need to define services dynamically in the config phase.
3. Manually Annotating Dependencies for Dynamic Injection
If you need to inject dependencies dynamically but avoid minification issues, you can use manual annotation.
Example: Injecting Dependencies Manually
app.controller('ManualInjectionController', ['$scope', '$http', function($scope, $http) {
$http.get('/api/data').then(function(response) {
$scope.data = response.data;
});
}]);
Why Use This?
- Protects against minification issues.
- Ensures dependencies are correctly injected even when variable names change.
Use array-style annotation when injecting dependencies dynamically in production.
4. Using $injector.invoke()
for Runtime Dependency Injection
If you have a function that requires dynamic dependencies, $injector.invoke()
can be used.
Example: Injecting Dependencies into a Function
app.controller('InvokeExampleController', function($scope, $injector) {
function fetchData($http) {
$http.get('/api/data').then(function(response) {
$scope.data = response.data;
});
}
// Inject $http dynamically into fetchData function
$injector.invoke(fetchData);
});
How It Works?
$injector.invoke(fetchData)
automatically injects$http
intofetchData()
.- Useful when working with external libraries or generic functions needing DI.
Use $injector.invoke()
when injecting dependencies into functions dynamically.
5. Dynamically Injecting Dependencies in Services
You can dynamically inject dependencies within a service using $injector
.
Example: Conditional Service Injection
app.factory('DynamicFactory', function($injector) {
return {
fetchData: function() {
var $http = $injector.get('$http'); // Injecting dynamically
return $http.get('/api/data');
}
};
});
Why Use This?
- This technique ensures that dependencies are only injected when required.
- Helps in lazy loading services for optimization.
Use $injector.get()
in services when you want to inject only when needed.
6. When to Use Dynamic Dependency Injection?
Scenario | Solution |
---|---|
Need to inject a service based on conditions | Use $injector.get('ServiceName') |
Need to register a service dynamically | Use $provide.service() in .config() |
Need to protect injections from minification | Use array-style annotation (['$http', function($http) {...}] ) |
Need to inject into a function dynamically | Use $injector.invoke() |