Sometimes we would like to access that same data in both controller and link functions in Angular directive. Usually we add this data to the scope object. This has certain problems, for example exposing it to any child scope. Here is an alternative solution: add the shared properties to the controller instance itself, accessible in the link function. In this scenario, you can consider the controller function a typical constructor functions for new controller instance.
Page setup
Let us consider a simple angular application with several instances of directive "foo". I will add a different id attribute to each instance to show they are different.
1 |
|
The angular directive code is very simple
1 | angular.module('App', []) |
When run, this prints to the browser console
"controller foo"
"linking foo 1"
"controller foo"
"linking foo 2"
"controller foo"
"linking foo 3"
Let us imagine that we would like to share some data between the controller function and the link function.
Typically we just add the shared data as a property of the scope, available in the controller
function via injected name $scope
and in the link function as first argument (named scope
by convention).
1 | angular.module('App', []) |
output
"controller foo"
"linking foo 1 shared ok"
"controller foo"
"linking foo 2 shared ok"
"controller foo"
"linking foo 3 shared ok"
You can see this program at shared through scope.
I do not like polluting the scope object with data that only needs to be shared between controller and link function in the same directive. Properties attached to the scope are available by default in every child scope (unless the child directive limits it). A good solution for sharing is to notice that the controller is a constructor function. It runs for every new instance of the directive, and is available as 4th argument to the link function by default.
1 | angular.module('App', []) |
output
"controller foo"
"linking foo 1 shared ok"
"controller foo"
"linking foo 2 shared ok"
"controller foo"
"linking foo 3 shared ok"
The above source version is available here.
Properties on controller visible via require
The sharing via controller instance properties is semi-private. The properties are not available
via the scope object, but the controller instances can be injected into child directives using
require
syntax. See Creating Directives that Communicate.
1 | <body ng-app="App"> |
Notice the bar
directive inside the third foo
directive.
1 | angular.module('App', []) |
output (you can see this version here).
"controller foo"
"linking foo 1 shared ok"
"controller foo"
"linking foo 2 shared ok"
"controller foo"
"bar link can see foo ok"
"linking foo 3 shared ok"
As you see, if a directive requires a controller from a directive up the DOM tree, the 4th argument to the link function becomes the required controller instance. Still I think this is more private than sharing via the scope variable.