1

I am wondering what the correct angular way to access the main html template element. I can use getelementbyid and also can access it using attr.$$element[0] but wondering if there is a cleaner way. In the example below I would like the equivalent of the getElementById line.

var app = angular.module('test', []);
app.directive('test', function(){
  return {
    restrict: 'E',
    template: '<canvas id="test-canvas"></canvas>',
    replace: true,
    link: function(scope, elem, attr) {
      // what is angular way of doing this?
      var canvas = initCanvas(document.getElementById("test-canvas")),
      // this works - is this recommended method?
      var canvas = attr.$$element[0];

    }
  };
});
cyberwombat
  • 38,105
  • 35
  • 175
  • 251
  • 1
    If you want to access the 'main html template element' just use the `elem` param. It's already a reference to the template root element. – bmleite Jan 28 '13 at 00:58
  • In the link function, `elem` is a jQuery (or jQuery lite) wrapped DOM element corresponding to the element the directive is operating on. However, it's possible in some cases that this is a _copy_ of the original element, which may or may not be important for your needs. You can get the _actual_ original element in these rare cases via the `compile` function of the directive. – Michelle Tilley Jan 28 '13 at 02:58
  • First thing I tried but it doesn't work. It is the element but not in the same format as that returned by the other options and it's not useable for me - in my case I want to do some canvas work and need to call canvas.getContext('2d') - and getContext is not a function of elem. – cyberwombat Jan 28 '13 at 02:59
  • Actually elem[0] works - why the array call though? – cyberwombat Jan 28 '13 at 03:26
  • 3
    Because `elem` is a jQuery wrapped element. `elem[0]` returns the raw element that has been wrapped. See http://stackoverflow.com/a/1677910/62082 – Michelle Tilley Jan 28 '13 at 03:30
  • 2
    Ahhh!! I got it - it doesnt look like Angular has the .get() function so I guess elem[0] would be the way to go for my needs. If you post your comment as an answer I'll mark it as accepted. – cyberwombat Jan 28 '13 at 03:45

1 Answers1

1

You should just use elem param like so:

var canvas = elem;

it's a jqLite (jQuery) wrapped element as was mention in the comments.

or

var canvas = elem[0];

to get a raw element.

If you want to get access to children elements and do something with them, you should use angular.element. Angular uses jqLite, it provides limited jQuery methods. You can read further here: Angular's jqLite. For instance, in jqLite you can use find() only with the tag name selector, so if you want to select the child by id you should use something like that:

angular.element(elem[0].querySelector('#your_child')).bind('click', () => {
  elem.toggleClass('some_class');
}

If you are using jQuery, you are able to use find(), then the code will look like that:

elem.find('#your_child').click(() => {
    elem.toggleClass('some_class');
});

Try out console.log(elem) you will see what it is. Hope this helps!

P.S.: Let's say you want to select child elements from the ng-repeat directive. The previous solutions won't work because these elements don't exist yet. All you need to do is to add $timeout like so:

function yourDirective($timeout) {
  return {
    ...
    link: function (scope, elem, attrs) {
      $timeout(() => {
        angular.element(elem[0].querySelectorAll('.your_child')).bind('click', () => {
          // Do something
        }
      });
    }
  }
}

angular
  .module('yourApp')
  .directive('yourDirective', yourDirective);
Frelseren
  • 531
  • 4
  • 11