How do I know what parameters can be injected - angularjs

I'm wondering where and if there's a documentation on what can be injected into a function with dependency injection.
I understand that all registered services/factories in angularjs can be injected but when stumbling upon a solution to a problem I had, I read about the following:
function AppController($scope, $element, $compile) {
// ...
}
So from the tutorials I know $scope (but I did not find anything about $scope or scope in http://docs.angularjs.org/api/ - all I found was $rootScope).
Same with the $element. But $compile is a service just like $http - I understand where they come from.
Obviously I'm missing a very basic point about dependency injection and would be happy if someone could explain it to me.

$rootScope is an instance of $scope, and $scope docs are found here: http://docs.angularjs.org/api/ng.$rootScope.Scope
$element is implicitly injected into compile, controller and linking directive functions and is explained here: http://docs.angularjs.org/api/ng.$compile
While $rootScope can be explicitly injected anywhere you want, $element is available only inside the directives.

Related

bindToController how to get rid of all the $scope ($scope.$on)

I'm implementing an AngularJS directive on Angular 1.4.12 using the controllerAs and bindToController "pattern" in order to have a clean controller which doesn't depend on $scope.
However I still find hard to get rid of $scope on these lines:
$scope.$on( '$destroy', function() {...} );
$scope.$on( '$stateChangeSuccess', function() {} );
Any idea how to handle this case?
Thanks
The idea behind not using $scope is to:
not pollute the HTML with variables that have no context and potentially have conflicting variable names in the same scope.
ng-model="name" VS ng-model="userController.user.name"
not pollute you javascript code by preceding every variable and
function with $scope
If you need to broadcast events or watch changes, it's perfectly fine to use $scope (especially if you have no alternative like .components in angular 1.5)
See $scope as a service provided to you by Angular just like $window or $state.
If you need it, you can use it. (but don't go and put code in there, even if you can)

What locals can be injected into a controller besides $scope?

Things in Angular can be injected with dependencies. But, injecting $scope into a directive won't work for example. Is there a concrete list of what is injectable into a controller or what isn't? What is injectable into a directive and what isn't? What is injectable into a service and what isn't? Etc? A comprehensive list of injectable/not injectable all in one place? The docs seems to have this info spread around, but it's hard to navigate.
You can read everything in the docs. In case you mis-typed your controller:
angular.module('app', []).controller('controllerName', ['$scope', function($scope) {
// Your controller logic
}]);
The controller is injectable (and supports bracket notation) with the following locals:
$scope - Current scope associated with the element
$element - Current element
$attrs - Current attributes object for the element
$transclude - A transclude linking function pre-bound to the correct transclusion scope
For more information, see AngularJS Comprehensive Directive API - controller.

$rootScope in angularjs custom property gone after injection

Problem Related codepen
I declared $rootScope.myproperty in main controller and it can be accessed in other controllers.
But in one of the controller I have to inject $rootScope as I used $watch. Then when I check back $rootScope.myproperty it became undefined. Strange why would this happens?
It was happening because you were using $rootScope as a variable and assigning an object to it
$rootScope = { myproperty: 'root abc' };
This is wrong. Instead you should add attributes to it as below and it will work:
$rootScope.myproperty = 'root abc';
I have updated the codepen and its working : http://codepen.io/anon/pen/RaeyJm
Working Demo
The problem is you have injected $rootScope into AttendeesCtrl controller. You don't need to inject $rootScope into a controller. When you inject $scope, you automatically get access to anything defined in $rootScope due to the prototypal inheritance of JavaScript. So AttendeesCtrl controller should look like this:
.controller('AttendeesCtrl', function($scope) {
//I used $watch and $rootScope somehere so I have to inject $rootScope in this controller
$scope.myproperty = $rootScope.myproperty;
});
For detail, you can have a look at the AngularJS Scope Hierarchies.
Hope that solve your problem.

vm.$on undefined error in angularjs

I am following this best practice style guide for angular development and I can't seem to get this one part working cleanly.
Best Practice Style Guide:
https://github.com/johnpapa/angular-styleguide
It recommends to declare controllers by the following:
angular
.module('app')
.controller('feedController', FeedController);
function feedController(){
var vm = this; //My $scope variable
}
The problem is I am trying to use $on to add an event listener but it gives me an undefined error for vm.$on. A temporary solution I found was to inject $scope into the controller by the following:
FeedController.$inject = ['apiservice', '$scope'];
and call $scope.$on which works but I feel its inconsistent now. Is there a way to still use vm in a clean way.
You can see the full controller here https://github.com/bliitzkrieg/TrailerFeed/blob/master/app/components/feed/FeedController.js
this/vm refers to the instance of the controller, not the scope that is associated with that controller.
Events only exist on scopes, so to use the event system it is correct to inject $scope to get a reference to the controller's scope where $on is available.
angular
.module('app')
.controller('feedController', FeedController);
function feedController($scope){
var vm = this; // the instance of the controller
$scope.on(...) // the controller's scope
}

When to use '$injector' and just injector in angularjs?

In the documentation for angularJS injector, some of the code uses $injector, while some code uses just injector. I am confused. What are the differences between these two, and where are the appropriate places to use them? I also have the same question for $scope and scope.
When you want to use injector, scope, or any other build in angularjs provider as dependency of other service you need to prefix them with $, as angular by convention registers all build in providers with $ prefix, so scope is registered as $scope, injector as $injector etc.
When angular instantiates objects(using injector btw) it checks what dependencies object has (as it needs to inject them) and the way it's done is by checking variables names of constructor function of that object, so that's why it's so important to name variables correctly or you'll get error unknown provider ...
When you retrieve injector as following:
var injector = angular.injector(['gaad', 'components']);
you don't use $ prefix, as it's normal variable and actually you can call it whatever you want ($injector included).
When you want to have injector as dependency, you need to name it as following:
angular.module('app').factory('$exceptionHandler', function($injector) {
...
});
or (convention needed when you use minification of angularjs scripts):
angular.module('app').factory('$exceptionHandler', ['$injector', function(anyNameYouWant) {
...
}]);
Similar for scope, when used in link function in directive:
link: function(scope, element, attr) {
}
you don't have to call it $scope as nothing is injected here. It's only one of function parameters. You can call it whatever you want, but convention here is to use scope not $scope to differentiate cases when scope is injected and when is used as parameter.

Resources