ng-if and the $transclude function problem

985 views
Skip to first unread message

Paul Selden

unread,
Jul 18, 2015, 7:50:57 PM7/18/15
to ang...@googlegroups.com
I've got a "multi-transclude" service in my application which simply calls the $transclude function in a directive's postLink function and does a mapping of elements with "transclude-id" in the directive's template to elements with "transclude-to" in the transcluded content.

For instance, the directive's template might look like this:

myDirective:

<div>
   
<div transclude-id="top"></div>
   
<div>Hello World</div>
   
</div transclude-id="bottom"></div>
</div>


And the usage might look like this:

<my-directive>
   
<div transclude-to="top">I'm above."</div>
   
<div transclude-to="bottom">I'm below.</div>
</my-directive>



Everything works fine until I try to use it with transcluded content that also contains an ng-if directive, for instance:

<my-directive>
   
<div transclude-to="top" ng-if="showTop">I'm above."</div>
   
<div transclude-to="bottom">I'm below.</div>
</my-directive>

In this scenario, by the time I call the $transclude function, the element with ng-if on it has already been replaced by a comment node: <!-- ngIf: showTop --> So when my service examines the node it does not find the transclude-to attribute and thus does not place it correctly.

I tried changing priority to make it higher (or lower) than ng-if but no matter what I try it is always already replaced by that node.

Does anyone have any insight as to what is going on? I verified that my directive is being called before ng-if's link function, yet it's still gone during this call:

$transclude($scope, function(clone) {
   // the clone nodeList contains the comment instead of the transclude-to="top" node :(
});

Thanks!

Sander Elias

unread,
Jul 19, 2015, 1:13:07 AM7/19/15
to ang...@googlegroups.com
Hi Paul,

The easy way out? use ng-show, for a small part, that is not an issue. If you part is bigger, put the ng-if inside your tag.

<div transclude-to="top"><div ng-if="showTop">I'm above."</div></div>

Transcluding, and ngIf are difficult to combine. It can be worked around, but its a lot of work. A simple solution might be, check in your transclude-to directive if there is an $attrs.ngIf, and log a warning to the console (or even throw an new Error('transclude-to does not support ngIf"))

Regards
Sander 

Paul Selden

unread,
Jul 19, 2015, 1:55:13 PM7/19/15
to ang...@googlegroups.com
Thanks for the reply Sander,

Yes I do think a good workaround would be to use show instead.

I am interested in the "It can be worked around" piece of your advice -- I'm ok with adding some complexity to my service/directives as long as it doesn't add much complexity to the consuming code.

Thanks,
Paul

Sander Elias

unread,
Jul 20, 2015, 1:32:20 AM7/20/15
to ang...@googlegroups.com
Hi Paul,

Well, if you want to tackle this, start of with logging every step in your program, analyze what happens with enabling/disabling the ngIf. You have to get familiar with the complete flow of your app, We are not talking about some complexity. It gets hairy because you are using multiple scope manipulating directives on a single element.
It is really better to avoid this altogether! (hence my advice on moving the ngIf to the inside of your element. Check for ngIf in your directive and throw an error is a better, and more maintainable solution!

Regards
Sander

Reply all
Reply to author
Forward
0 new messages