Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS - Access isolated scope in directive's link function

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. :)

like image 258
pdegand59 Avatar asked Jun 14 '13 14:06

pdegand59


People also ask

What is isolate scope in AngularJS?

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.

What is Link function is used for in AngularJS?

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.

How do you access $scope in console?

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 .


2 Answers

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.

like image 131
Mark Rajcok Avatar answered Nov 02 '22 23:11

Mark Rajcok


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

like image 44
Dan Avatar answered Nov 03 '22 00:11

Dan