I'm giving a first try at AngularJS custom directives.
I'm having trouble using (or understanding ...) the isolated scope in the link function of the directive.
Here is the code of this part of my app :
view.html
... <raw-data id="request-data" title="XML of the request" data="request">See the request</raw-data> ...
request
is a variable published in the scope of the viewCtrl that contains the xml-string of a request.
rawData.js
directives.directive('rawData', function() { return { restrict : 'E', templateUrl : 'partials/directives/raw-data.html', replace : true, transclude : true, scope : { id : '@', title : '@', data : '=' }, link : function($scope, $elem, $attr) { console.log($scope.data); //the data is correclty printed console.log($scope.id); //undefined } }; });
raw-data.html
<div> <!-- Button to trigger modal --> <a href="#{{id}}Modal" role="button" class="btn" data-toggle="modal" ng-transclude></a> <!-- Modal --> <div id="{{id}}Modal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="{{id}}Modal" aria-hidden="true"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> <h3 id="myModalLabel">{{ title }}</h3> </div> <div class="modal-body"> <textarea class="input-block-level" rows="10">{{ data }}</textarea> </div> <div class="modal-footer"> <!-- <button class="btn" ng-click="toggleTagText('')">{{'cacher'}} l'image</button> --> <button class="btn btn-primary" data-dismiss="modal" aria-hidden="true">Fermer</button> </div> </div> </div>
I don't understand why the ID is correclty shown when the modal pops, but when I try to console.log()
it, its value is undefined.
Maybe i'm wrong with the isolated scope value (=
and @
).
Thank you for reading. :)
Isolated scope directive is a scope that does not inherit from the parent and exist on its own. Scenario: Lets create a very simple directive which will show the object from the parent controller.
Link: The link function deals with linking scope to the DOM. Using Code for Compile. While defining a custom directive we have the option to define a link against which either we can define a function or we have the option to assign an object which will have pre & post function.
scope(); $('#elementId'). scope(). $apply(); Another easy way to access a DOM element from the console (as jm mentioned) is to click on it in the 'elements' tab, and it automatically gets stored as $0 .
Isolate scope properties bound with @
are not immediately available in the linking function. You need to use $observe
:
$attr.$observe('id', function(value) { console.log(value); });
Your template works properly because Angular automatically updates isolate scope property id
for you. And when it does update, your template automatically updates too.
If you are just passing strings, you can simply evaluate the values once instead of using @
binding:
link: function($scope, $elem, $attr) { var id = $attr.id; var title = $attr.title console.log(id, title); }
However, in your case, since you want to use the properties in templates, you should use @
.
If you weren't using templates, then @
is useful when attribute values contain {{}}
s – e.g., title="{{myTitle}}"
. Then the need to use $observe
becomes more apparent: your linking function may want to do something each time the value of myTitle
changes.
This is intentional and has to do with compilation order and the difference between '@' and '='.
Some excerpts from this Google Groups discussion with input from Misko:
@ and = do very different things. One copies the attribute value (which may be interpolated) and the other treats the attribute value as an expression.
@attrs are not $interpolated until later, so they are not available at link time. If you want to do something with them in the link function you either need to $interpolate yourself manually
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With