1

The Problem

Let's say we have a page template written as a Web component in a shared library to keep the company design system consistent. That page has some slots:

export class PageTemplate extends LitElement {
  static properties = {
    title: { type: String },
  };
  render() {
    return html`
      <div>
        <h1>${title}</h1>
        <slot name="template-body"></slot>
        <div class="some-special-styles">
          <slot name="template-buttons"></slot>
        </div>
      </div>
    `;
  }
}

customElements.define("page-template", PageTemplate);

Then we use this template in a Vue (v3.2.45) application on a base component to be used in the same app by multiple pages.

//page-base.vue
<template>
  <page-template title="My App Name">
    <slot name="base-body"></slot>
    <slot name="base-buttons"></slot>
  </page-template>
</template>

Here, we will use the page base vue component on a specific page.

//login-page.vue
<template>
  <PageBase>
    <template #base-body>
      <div slot="template-body">
        <input placeholder="some special code"/>
      </div>
    </template>
    <template #base-buttons>
      <button slot="template-buttons">login</button>
      <button slot="template-buttons">back</button>
   </template>
  </PageBase>
</template>

To make the login page components show inside that original page template web component; we need to declare the slot property on the leaf components like in <button slot="template-buttons">

How can I implement the Vue Page Base component to avoid the need to remember to set the slot property in every leaf vue component?

Things I've Tryied

I've tried to solve this using the vanilla web syntax below, but Vue appears not to dispatch that information to the final HTML:

//page-base.vue
<template>
  <page-template title="My App Name">
    <!-- this does not work -->
    <slot name="base-body" slot="template-body"></slot>
    <slot name="base-buttons" slot="template-buttons"></slot>
  </page-template>
</template>

There was also an attempt (after a suggestion in the comments) to use a template as a ghost intermediate in the page base. But nothing was rendered at runtime.

//page-base.vue
<template>
  <page-template title="My App Name">
    <!-- i can't have that span because of some-special-styles applied in the template-->
    <template slot="template-body"><slot name="base-body"></slot></template>
    <template slot="template-buttons"><slot name="base-buttons"></slot></template>
  </page-template>
</template>

The approach to using some middle element to make the connection (like below) enables content rendering. Still, it does not work for the project requirements because, for style reasons, I need that the final components be the top-most nodes in the page template slots.

//page-base.vue
<template>
  <page-template title="My App Name">
    <!-- although it runs, i can't have these spans because of some-special-styles applied in the template -->
    <span slot="template-body"><slot name="base-body"></slot></span>
    <span slot="template-buttons"><slot name="base-buttons"></slot></span>
  </page-template>
</template>
João Melo
  • 784
  • 6
  • 16
  • The slot is useful to access sections in the document, but if i understand well, you want to be capable of insert many buttons using the same named slot, which is not possible. Maybe you can pass the button properties to the page template and let the template draw them, or you can create another button or button group component to do that – rafaelmi Jan 31 '23 at 17:15
  • Have you tried using template instead of a span tag (like ``)? – Bernard Borg Jan 31 '23 at 18:35
  • hi @BernardBorg. i tried just now after reading your recommendation. unfortunately, it didn't work. thanks for the suggestion. – João Melo Feb 02 '23 at 11:23
  • @rafaelmi. multiple components in the same slot is possible in the HTML spec. that is working fine for me and is not my struggle. I want to pass the grandchild vue template content to the grandparent web component slot without using a intermediate element and avoiding the need for the grandchild to know the grandparent slot name. thanks. – João Melo Feb 02 '23 at 11:27

0 Answers0