AngularJS: is there a difference between $ transclude local in a directory controller and the transclude parameter in a link function?

I implemented a directive that includes several fragments of child content in a template. It works, but it seems simpler than most of the examples I've seen, and raised a few questions about how transcription works.

Here is the directive:

module.directive('myTransclude', function() { return { restrict: 'A', transclude: true, replace: true, scope: true, template: '<div style="border: 1px solid {{color}}"><div class="my-transclude-title"></div><div class="my-transclude-body"></div></div>', link: function(scope, element, attrs, controller, transclude) { // just to check transcluded scope scope.color = "red"; transclude(scope, function(clone, scope) { Array.prototype.forEach.call(clone, function(node) { if (! node.tagName) { return; } // look for a placeholder node in the template that matches the tag in the multi-transcluded content var placeholder = element[0].querySelector('.' + node.tagName.toLowerCase()); if (! placeholder) { return; } // insert the transcluded content placeholder.appendChild(node); }); }); } } }); 

and here is a usage example:

 <div ng-controller="AppController"> <div my-transclude> <my-transclude-title> <strong ng-bind="title"></strong> </my-transclude-title> <my-transclude-body>My name is {{name}} and I've been transcluded!</my-transclude-body> </div> </div> 

You can see it in action in this fiddle .

Pay attention to a few things:

  • It maps fragments to template placeholders by element classes, rather than explicitly defined child directives. Is there any reason to do this anyway?
  • Unlike many of the examples I saw, it clearly does not use the $ compilation service on child fragments. Angular seems to compile fragments after shutdown, at least in this simple case. Is it always right?
  • It uses the (barely documented) argument transclude for the link function, and not another (barely documented) approach for embedding $ transclude local in the controller directive. Having heard so many warnings about not manipulating the DOM in controllers, the approach to the controller looks like an odd construct, and it’s more natural to handle this in the link functions. However, I tried it this way and it seems to work the same. Is there a difference between the two?

Thanks.

EDIT: partially answer the question No. 2, I found that you need to explicitly compile excluded content that is not cloned from the template in which the directive was applied. See the difference in behavior here: http://jsfiddle.net/4tSqr/3/

+8
angularjs angularjs-directive
source share
2 answers

To answer the question about the differences between the $ transclude function in the controller vs binding directive, we first need to understand that the $ transclude function can be accessed through the directive to compile , controller and binding .

UPDATE . According to the 1.4 documentation Angular compile (switch) was deprecated ! Therefore, the transclude function can only be accessed in your Controller or Communications directive. (See Official Documentation for a detailed explanation )

There is a big difference when using $ transclude in the compile phase compared to $ transclude in the controller and binding to the phase due to the compilation phase, you do not have access to $ scope or to use functions in the controller and binding where $ scope (controller) is available and scope (linking). With that said, the only difference is when using $ transclude in the directory controller and binding the execution order . For a few nested directives, it is relatively safe to use $ transclude during the bind phase instead of using it in your controller.

The order is as follows:

  • parentDirectiveCompile -> childDirectiveCompile (directive assembly)

  • parentDirectiveControllerPre, parentDirectiveControllerPost -> childDirectiveControllerPre, childDirectiveControllerPost (directory controller)

  • childLinkFunction β†’ parentLinkFunction

Note that the childLinkFunction function is executed first before the parentLinkFunction? (Execution Order)

Useful resource :

  • Angular directives - when and how to use compilation, controller, prelink and post link

I hope this answer may be useful to you!

+2
source share

after some research:

After the release of Angular 1.20, the existing child nodes of a compiled directive that has a selection region will no longer inherit the new selection region, since they have already been assigned to the parent region. So ... the built-in transclude method, which uses the ng-transclude attribute, will only translate the templates to the right place in this case, but the previously existing html will not go to this location. This means that if you have a directive with a selection area and you want html that has already been compiled for the new selection area, you would need to use the link transclusion function inside the directive.

Here you can see a working example of this problem. ui-codemirror placed in user directives fails without errors

0
source share

All Articles