This is my app config:
angular.module('myApp', ['myApp.directives', 'myApp.controllers', 'myApp.services']);
This is my controller:
angular.module('myApp.controllers', [])
.controller('MainCtrl', function ($scope) {
$scope.name = 'world';
});
This is my directive:
var directives = angular.module('myApp.directives', []);
directives.directive("hello", function () {
return function (scope, elm, attrs) {
elm.text("hello, " + scope[attrs.name]);
};
});
and this is my html:
<div ng-controller="MainCtrl">
<h1 hello></h1>
</div>
The is problem is that angular render the directive as:
hello, undefined
Instead of:
hello, world
What is wrong?
You are accessing scope[attrs.name]
but the directive doesn't provide a value for the attribute name
There are 2 options:
Change the directive to elm.text("hello, " + scope['name']);
This is not a preferred way as it hard codes to a scope property name
Change the html to <h1 hello name="name"></h1>
. This is better but I feel it uses a redundant attribute
I would suggest you change the directive to elm.text("hello, " + scope[attrs['hello']]);
Or even better elm.text("hello, " + scope.$eval(attrs['hello']));
this way you get the benefit of expressions as well(ex: <h1 hello="name|uppercase"></h1>
)
demo
This way the html would be <h1 hello="name"></h1>
Regarding the attrs parameter: it's nothing more than a map of strings taken from the attributes present on the dom element.
You can do something that, as of writing this, appears to be undocumented in Angular (see Mark Rajcok's comment here: http://docs.angularjs.org/api/ng.$rootScope.Scope).
From within your directive:
scope.$parent.name
If you do a console.log(scope)
on the directive's scope
(from within the directive), you'll see these properties.
All this said, I don't know whether or not this is "proper" Angular convention, due to the fact that this is both undocumented, and I haven't found any other better documentation on how to access the controller that a directive sits within.
You can access using scope
. Look http://jsfiddle.net/rPUM5/
directives.directive("hello", function () {
return function (scope, elm, attrs) {
elm.text("hello, " + scope.name);
};
});
I found another case:
if you are accessing a variable coming from a Ajax request body, then you have to WAIT until the variable is set.
e.g:
# in controller
$http.get('/preview').then( (response) ->
$scope.tabs = response.data.tabs
$scope.master_switch = '1'
console.info 'after get response in controller'
)
# in directive
directive('masterSwitch', ->
(scope, element, attrs) ->
alert 'in directive!' # will show before "after get response in controller"
console.info scope.master_switch # is undefined
setTimeout( -> console.info(scope.master_switch), 50) # => 1