zachsnow / ng-multi-transclude

ng-multi-transclude
MIT License
79 stars 19 forks source link

Support for transcluding same block multiple times. #10

Closed kbaltrinic closed 8 years ago

kbaltrinic commented 10 years ago

It is possible to put multiple ng-transclude directives in the same template, in order to transclude the same elements more than once. We use this to transclude the same set of action buttons into the top and bottom of a directive that produces a long page.

Trying to replicate this with ng-multi-transclude by including multiple ng-multi-transclude directives with the same value does not work in the same way. What happens is that the trancluded block gets appended to the first location by the first ng-mutli-transclude directive. When the second directive attempts to append the same block to a different location, the block gets removed from the original location. This is happening because the same instance of the htmlElement DOM object that is being appended, and the same node cannot be attached to multiple locations in the DOM tree.

The difference is that ng-multi-transclude, due to the test at Line 90 only calls the angular $transclude function once per ng-multi-transclude-controller, in order to avoid re-linking scope. This however, breaks the ability to re-transclude the same block as the append call does not get a new clone each time.

I have confirmed this by disabling the if on line 90 and things work again. Since I am not clear on negative impact of relinking to other use cases, I am not certain as to what the correct solution is. Can you advise?

zachsnow commented 10 years ago

So, to be clear, you'd like to be able to do something like this:

<div>
    <div ng-multi-transclude="thing1"></div>
    <div ng-multi-transclude="thing2"></div>
    A bunch more stuff.
    <div ng-multi-transclude="thing1"></div>
<div>

And you'd like the passed block corresponding to thing1 to be linked twice, but thing2 to only be linked once.

kbaltrinic commented 10 years ago

Sorry for the delay, I seem to have missed your response. Yes, that is exactly correct.

zachsnow commented 10 years ago

This seems to be kind of tricky since we are relying on the built-in transclusion machinery.

As you suggest, removing the check that guards against relinking works, but leads to surprising behavior (where the entire block is relinked once per ng-multi-transclude, triggering all of the directives multiple times). We could possibly allow specifying whether or not to relink per block at the controller level, so that if you know that your directives are safe to run multiple times you can opt-in to that behavior.

kbaltrinic commented 10 years ago

I agree there does not seem to be a good solution from the standpoint of the built in transclusion capabilities. At this point we are rolling our own because we also need to deal with the ng-repeat issues that I think you alluded to in another ticket. The problems become slightly more tractable when we deal with them in our limited case vs trying to come up with a general purpose solution.

zachsnow commented 8 years ago

Maybe this works with AngularJS 1.5 and "multi-slot transclusion" -- in any event this library is now obsolete, see https://docs.angularjs.org/api/ng/directive/ngTransclude#multi-slot-transclusion