Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Directive has no access to transcluded elements?

I might get some concept terribly wrong, but I don't get this to work I expected: http://plnkr.co/edit/Qe2IzMMMR5BJZJpwkx9e?p=preview

What I'm trying to do is to define a directive that gets attached to a top-level <nav> element, and then modifies the contained DOM elements in its link function (such as adding css classes to <li> etc.). However, the link function seems to only get the original directive template (<nav><ul><ng-transclude/></ul></nav), and not the transcluded/expanded DOM elements.

If this is "by design", how should I do this? It find it pretty useless to define a transcluding "root" directive, if it does not have access to the transcluded DOM tree....

like image 436
Florian Avatar asked Jan 21 '14 18:01

Florian


2 Answers

Please read some of my answers about transclusion in angular:

  • What is the main use of transclusion in angularjs
  • Why I can't access the right scope?

As to your question:

  • First, it's not useless , even if not fit to your use case.
  • Yes, it's by design - but it's just the default behavior of ng-transclude.
  • If it was the opposite then everyone would be yelling about scope leaking.
  • You can do anything you want with $transclude, just be careful.
  • There are probably better solutions like creating isolated scope with bindings.

This is what you wanted (plunker):

angular.module('app').directive ('myNav', ['$timeout', function($timeout) {
  return {
    replace: false,
    transclude: true,
    template: '<nav><ul></ul></nav>',
    link: function (scope, element, attrs,ctrl,$translcude){
      $transclude(scope,function(clone){
        element.find('ul').html(clone)
      });
      var items = element.find('li'); //element.find('ng-transclude') === 1 !
      window.console.log (items.length);
    }
  };
like image 71
Ilan Frumer Avatar answered Sep 30 '22 16:09

Ilan Frumer


(Correct answers see above from Ilan and others)

I finally got my (simple) use case working without transclude at all with the old dirty $timeout hack: http://plnkr.co/edit/FEEDYJLK9qRt0F4DNzRr?p=preview

link: function(scope, element) {
    // add to end of event queue
    $timeout(function() {
      var items = element.children('ul:first').children('li');
      window.console.log(items.length);
    }, 0);
  }

I know this is a bad thing to do, and not totally sure if this will work always, but at least seems to work for my simple case...

like image 27
Florian Avatar answered Sep 30 '22 17:09

Florian