angularjs - runtime dependency injection? - angularjs

Simple one I hope..
Here's a plunker for reference.
I know how to specify a dependency at compile-time (see MainCtrlInjected controller). But how do I pull down a dependency at runtime, giving the name of that dependency? (see MainCtrlInjectedRuntime controller)

You can use $injector to get your value at runtime:
Check my forked plunker: http://plnkr.co/edit/iVblEU?p=preview
Code:
app.controller('MainCtrlInjectedRuntime', [
'$scope',
'$injector'
($scope, $injector) ->
nameValHandle = 'nameVal'
# !!! This is how you inject at runtime
name = $injector.get(nameValHandle)
$scope.name = name
])

I am just getting into angularjs, but I believe the appropriate way to handle this situation would be to inject a service into MainCtrlInjectedRuntime. The injected service would have your somehowGetNameFromValue method.

Related

angularjs: How to inject a dependency into a controller

I try to inject a dependency into a controller. I have tried passing dependencies through an Array, through an inline anonymous function and to use controller.$inject. Nothing works and I'm ready to explode.
Most of the blogs and article that mention dependency injection shows a simple example, where the code passes the $scope and a dependency.... but when I try to replicate the code example nothing works.
There is something that I'm missing. Do I have to instantiate the dependency or how do I pass the dependency?
var myApp = angular.module('myApp', []);
function MyViewModel() {
this.theRightAnswer = 'The answer is 42';
}
myApp.controller('myController', ['$scope', 'MyViewModel', function ($scope, MyViewModel) {
$scope.theAnswer = MyViewModel.theRightAnswer;
}]);
Use either service/ Factory/ provider for that, & then through dependency Injection you can share the functionality in different controllers. Add following line in your code & it'll work as expected.
myApp.service('MyViewModel', MyViewModel);
http://plnkr.co/edit/7ZclGB93Soq5Ce8pFmkQ?p=preview

Angular 1 - Get the module a controller is running in

I am working inside a platform where you can create controllers using a web form and write angular code inside of them... but I do not have access to the parent module.
So here I am in my module, trying to apply a filter but I cannot apply a filter if I do not know the module.
Is there any way I can find out what module I am running in from a controller?
I only have access to this code:
function ($scope, spUtil, snRecordWatcher, $rootScope) {
}
I cannot see the angular.module(blabla)
Thank you,
Alexandru S.
If you inject $rootElement you can use it to find the name of the module under which the current controller is running. e.g.:
function ($scope, spUtil, snRecordWatcher, $rootScope, $rootElement) {
var module = $rootElement.attr('ng-app');
}

Angularjs dependency injection, array, $inject, factory

I'm kind of a big angularJS newbie and I'd like some highlights concerning dependency injection.
I've done some research and here is what I understand so far.
I have 2 service files (using factories) :
-mogService.js
angular.module('anglober.services').factory('mogService', ['$http', function($http) {
var mogService = {};
//mogService code here
return mogService;
}]);
-modalService.js
angular.module('anglober.services').factory('modalService', ['$modal',
function ($modal) {
//modalService code here
}]);
One controller file :
-mogCtrl.js
angular.module('anglober.controllers').controller('mogCtrl', ['$scope', 'mogService','modalService', function ($scope, mogService, modalService) {
//code using mogService and modalService parameters
}]);
As I understand it, the dependency injection is done by passing my services as parameters of the function parameter in my controller declaration, the array of string is here so that after minification, angular still knows which variable is what.
However, the modalService variable is undefined when I test my code. The mogService is recognized alright though (only if I remove any call to the modalService variable).
What am I doing wrong ?
I've read things about using $inject, which is the better practice and why ?
I'm declaring modules in the app.js as follows :
angular.module('anglober.services', ['ui.bootstrap']);
angular.module('anglober.controllers', []);
var app = angular.module('anglober', ['anglober.controllers', 'anglober.services', 'anglober.directives']);
Is this good practice ? Declaring modules and their respective dependencies in one file then only use "getters" without the dependencies array parameter in module files ?
Thanks for your time.
Three steps that work for me (plunkr):
1. Be sure you define a module's dependencies only once.
Indeed, check that angular.module('anglober.services', [...]); is indeed called only once with the second argument.
At the same time, be sure to call these lines before the actual services/controllers /... definitons.
2. Wire every dependency
You should add 'anglober.services' dependency to 'anglober.controllers': the last requires modalService which requires $modal, it may help angular anyway.
3. Add possible missing lib requirements, in the right order
First jQuery, then angular, bootstrap and eventually bootstrap.ui and your modules.

AngularJS - dependency injection

I would like to know if there is a difference between the two next lines and why to use one of those (the two work as expected)
phonecatApp.controller('PhoneListCtrl', function($scope, $http) {...});
phonecatApp.controller('PhoneListCtrl', ['$scope', '$http', function($scope, $http) {...}]);
I took it from the official AngularJS tutorial and I know there is an explanation about this modification but I don't understand it...
http://docs.angularjs.org/tutorial/step_05
Thanks in advance!
If you minify your first line you get:
phonecatApp.controller("PhoneListCtrl",function(e,t){})
The dependency injection won't work then, because Angular has no idea what e and t are. Compare that to minifying the second version:
phonecatApp.controller("PhoneListCtrl",["$scope","$http",function(e,t){}])
The function parameters are still renamed, but $scope and $http are given in the array so the injection can go ahead as expected.
There is no difference in terms of functionality. The first one may get messed up if your code is minified because angular resolves from the argument names. The latter has some kind of protection against minification because you are already passing dependencies in array.
AngularJS invokes certain functions (like service factories and controllers) via the injector. You need to annotate these functions so that the injector knows what services to inject into the function. There are three ways of annotating your code with service name information:
Using the inline array annotation (preferred)
Using the $inject property annotation
Implicitly from the function parameter names (has caveats)
For more information, see AngularJS Developer Guide - Dependency Injection

Angular - Decorating Directives

I'm trying to use Angular's "decorator" capability to add functionality to some directives. Assume that my directive's name is myDirective. My code looks like this:
angular.module('app').config([
'$provide', function($provide) {
return $provide.decorator('myDirective', [
'$delegate', '$log', function($delegate, $log) {
// TODO - It worked! Do something to modify the behavior
$log.info("In decorator");
}
]);
}
]);
I keep getting this message:
Uncaught Error: [$injector:unpr] Unknown provider: myDirectiveProvider from app
To the best of my ability, the directives are already registered by the time the decorator function runs. Any insight would be appreciated!
This article shows how you can, in fact, use decorator() with directives.
You just have to include "Directive" as the suffix for the name. Hence, in my example I should have been doing
return $provide.decorator('myDirectiveDirective', ['$delegate', '$log', function($delegate, $log) {
// TODO - It worked! Do something to modify the behavior
$log.info("In decorator");
// Article uses index 0 but I found that index 0 was "window" and index 1 was the directive
var directive = $delegate[1];
}
http://angular-tips.com/blog/2013/09/experiment-decorating-directives/
Decorators as created with the decorator method are for services only. They have to be created with service, factory, provider or value. See the docs here.
If you want to decorate a directive, you can make another directive with the same name. Both directives will be used when the DOM is compiled, and you can define the compilation order using priority.
Alternatively, if you are able to modify the code that uses the directive you are trying to decorate, then you can just make a new directive that uses the original in its template.

Resources