DEV Community

Andrej Rypo
Andrej Rypo

Posted on • Updated on

Nested slots with Vue.js

Coming from the world of Twig and Latte (PHP templating engines), I was surprised that nested slots also work with Vue.js templates.

TL;DR the following Vue template works:

<!-- `base-layout`'s component template -->
<div class="component">
  <slot name="wrapper"> <!-- an outer slot -->
    <div class="wrapper">
      <slot> <!-- nested /inner slot -->
        Default slot's content.
        The slot is nested within another named slot.
      </slot>
    </div>
  </slot>
</div>
Enter fullscreen mode Exit fullscreen mode

Then, we can either provide content to the inner slot only (in this case, the default slot),

<base-layout>
  <p>A paragraph for the default slot.</p>
</base-layout>
Enter fullscreen mode Exit fullscreen mode

... or override the the whole wrapper instead.

<base-layout>
  <template v-slot:wrapper>
    <div class="wrapper my-wrapper">
      <p>A paragraph for the default slot.</p>
    </div>
  </template>
</base-layout>
Enter fullscreen mode Exit fullscreen mode

It enables us to create more flexible visual components without exposing multitude of props (e.g. for wrapper css).

The pattern works epsecially well with CSS frameworks like Bulma or Bootstrap that include pre-styled components that require particular wrappers to be used.
For the default usage, we need not know what wrapper classes have to be used for the components to render properly, but enables us to fine-tune them when the need arises.

Observe the following snippet to see it in action.
Note the difference between the two card components.

The surprise comes from the fact that this pattern is not mentioned in the Vue docs (as far as I can tell) and I was unable to find reference to it elsewhere either.

P.S.: Sections that are rendered in another templates are called "blocks" in both Twig and Latte templating engines.

Discussion (0)