How to use slot inside template?

I have the following custom element.

<!--my-el.html-->
<template>
  <br>
  template + slot
  <br>
  <template> <!-- <= inner template -->
    <slot></slot>
  </template>
</template>

And, I am trying to use it as follows.

<my-el>
  <another-ce></another-ce>
<my-el>

Now the problem is that the content from another-ce is never projected in the slot of my-el. I need the inner template in my-el to apply show.bind (omitted from the example). However, regardless of the binding applied on the inner template, the content is never projected. The rendered DOM for the inner template looks as follows.

<template>
  #document-fragment
  <au-shadow-slot class="au-target" au-target-id="1"></au-shadow-slot>
</template>

However, if I replace the inner template with something else (for example: <element><slot></slot></element>), it works. I am interested about knowing why the former approach does not work here.

1 Like

I think this has nothing to do with Aurelia but rather with the template tag.

See MDN:

When you use in aurelia, aurelia kicks in and controls whether the content should be rendered. Without any if/repeat- or other control blocks though, aurelia will do what it should and not render the content of the template tag.

In your case: the tags expresses where you want to project content, since this is inside a template tag, nothing gets rendered (and hence it works when using something other than a template).

2 Likes

Thank you for the explanation :slight_smile:

Just couple of follow-up questions.

As I have understood, Aurelia practically ignores a template without control bindings, such as if, repeat, etc. Does this mean that show.bind has practically no effect on the content of template? Is there any reason, why Aurelia ignores a show.bind in this case, although it processes if.bind? I am asking this because I have used similar construct involving template using if, and else bindings, which worked as expected and though I know the basic difference between if and show, in my head those are kind of synonymous in the context.

1 Like

show.bind would toggle the visibility of that element (using css), if.bind toggles the rendering of that element. The content within <template style="display: block"> should still not be rendered according to the spec. In fact, a template tag is not your typical container and hence ignores any styling anyway.

The template tag works a bit different here:

<template if.bind="true">foo</template>
<div if.bind="true">bar</div> 

would be rendered as:

foo
<div>bar</div>

Note how the template container tag gets removed. I found this particularly useful when doing something like this:

<table>
   <tr>
      <td>I'm always here</td>
      <template if.bind="...">
          <td>x</td>
          <td>y</td>
       </template>
   </tr>
</table>

That allows me to conditionally render multiple columns of that table without having to repeat my condition. Because I use the template tag, I know that the td’s will be inlined within the tr when that condition yields true.

It also helps me in being more expressive (and working around IE limitations) when it comes to combining if and repeat. I always find the following messy (who comes first, repeat or if? what if we mix in other attributes?):

<ul>
  <li if.bind="foo.z" repeat.bind="foo of bar">
  </li>
</ul>

Instead consider the following:

<ul>
   <template repeat.for="foo of bar">
       <li if.bind="foo.x"></li>
   </template>
</ul>
3 Likes

Succinct examples and explanation!! :slight_smile: Thank you again

2 Likes