Multilevel transclusion in Angular 1.5
I have a generic <item>
directive, and a <listing>
directive with filters and pagination tools for listing that <item>
:
Example : https://plnkr.co/edit/r6byzhFX5m674ONhH1JS?p=preview
The <listing>
template is something like this:
<div ng-repeat="item in items">
<item date="item">
<ng-transclude ng-transclude-slot="itemContent"></ng-transclude>
</item>
</div>
The <item>
directive uses the new Angular 1.5 multi-slot transclusion to customize footer and header easily:
<item data="itemData">
<header>My header</header>
<footer>My custom footer</footer>
</item>
My problem arises when I try to customize that items when using <listing>
. If I use something like this:
<listing items="myItems">
<item-content>
<header>{{ item.name }}</header>
<footer>My custom footer for {{ item.name }}</footer>
</item-content>
</listing>
It doesn't work, because the <item-content>
gets inserted into <item>
, but <header>
and <footer>
don't get transcluded into their proper places, and they cannot read the item
scope variable. Is there any way to achieve this?
First, in the listing template you should change ng-transclude-slot="itemHeader"
by ng-transclude="itemHeader"
and ng-transclude-slot="itemFooter"
by ng-transclude="itemFooter"
to get the transclusion to work.
Then, you have in single and list example a mistake. If you change in the provided plunkr {items[0].name}
by the expected {data.name}
in the single example you will see that the name is not being displayed anymore. The second thing to do is to fix this shared problem.
TL;DR; Working example: https://plnkr.co/edit/1ideOiohle8AEzkDJ333?p=preview
The basic problem you're running into is that when you transclude, the scope you have access to is the top level scope. What you want is to reference the item level scope from outside the directive.
So, instead of using transclusion on the listing directive, I bind a string template as an attribute. I have to use a compile function to pick up the raw string value before angular pulls out the {{}}
placeholders and then I use $interpolate
to create template functions itemHeaderTemplate
and itemFooterTemplate
which are then used in the template like so ng-bind-html="itemHeaderTemplate({item: item})"
.
Note: In order to use ng-bind-html
you need to include the ngSanitize
module or you'll get a security exception.
下一篇: Angular 1.5中的多级转换