2

I'm trying to get a better understanding how AngularJS compiles directives and updates the view.

Here's my specific problem. I have a directive like so:

angular.module('directives', [])

.directive('test', function() {
   return {
      restrict: 'AE',
      scope : { foo : '=' }, 
      template: '<div id={{foo.id}}>{{foo.data}}</div>'
      link: function(scope, element, attrs) {
          document.getElementById(scope.foo.id); /*1*/
      }
    }
 });

At point 1 scope.foo.id is defined. However, the template for the directive has not been compiled yet, so the div id is not set, and getElementById returns null. Once the page is completely rendered, and I look at the compiled template, all of the template id's have been successfully set to foo.id

What am I missing here?

It's also important to note that for my particular case I need to explicitly interact with the template div by it's id.

EDIT: added a fiddle : http://jsfiddle.net/6c4nb/8/

12
  • Question, it says you need to interact with the template, any details on what you want to do with that template? Commented Mar 28, 2014 at 16:25
  • I'm trying to initialize a plugin on the element that explicitly needs the element id to be passed into it. Commented Mar 28, 2014 at 16:28
  • Can you throw this into a fiddle? It is hard to understand exactly what you are doing without the html and full js. Commented Mar 28, 2014 at 16:32
  • Can you provide me with the HTML for your plugin? Essentially, what you do is use element.html( {{ your plugin goes here }} ); then execute a $compile(element.contents())(scope); Commented Mar 28, 2014 at 16:32
  • I'm working on a fiddle now. Commented Mar 28, 2014 at 16:32

1 Answer 1

3

Ok, given the limited information, I was able to get the element working for you. I'm not exactly sure what you want to do, but you need to set the id of the element within the directive.

If someone with better understanding can explain, I'd like to know why the id doesn't get bound within the template. It appears that if you set the id from the directive, it works fine. (jsfiddle)

@Dan I also had to change your ID to use the word test- in front of it because the HTML spec does not allow id's to start with numerical values. According to the spec:

ID and NAME tokens must begin with a letter ([A-Za-z]) and may be followed by any number of letters, digits ([0-9]), hyphens ("-"), underscores ("_"), colons (":"), and periods (".").

var testApp = angular.module('testApp',[]);

testApp.controller('mainCtrl', ['$scope', function($scope) {
    $scope.bar = [
        { id: 1, msg: 'this is a nice message'}, 
        { id: 2, msg: 'this message is also nice'}, 
        { id: 3, msg: 'yet another message'}
    ];
}]); 

testApp.directive('plugin', function() {
    return {
        restrict : 'EA', 
        template: '<div>{{foo.msg}}</div>',
        scope: {'foo': '='},
        compile: function compile(tElement, tAttrs, transclude) {
            return {
                post: function postLink(scope, element, iAttrs, controller) {
                    element.attr('id', 'test-' + scope.foo.id);
                    console.log(document.getElementById('test-' + scope.foo.id));
                    /* This does not provide a null value */
                }
            }
        }
    };
});
Sign up to request clarification or add additional context in comments.

6 Comments

Foo is defined on a controller, and I'm defining it on the scope of the directive with scope: {foo = '='}. I'm just trying to access it so I can do some DOM manipulation on the element.
Couldn't you just modify the DOM using the element variable? Any chance you could get a jsfiddle illustrating what you want?
Refer to the comment I made above. I need the id string, and the element needs to be compiled at that time.
Make sure you understand the scope setting for directives. You'll need the understand when to set scope to false/true/or {}. See the link in the answer.
I'm explicitly trying to isolate the scope... I don't want scope: false
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.