Subscribe on changes!

Slot attributes, props, and directives

avatar
Jul 5th 2023

What problem does this feature solve?

Currently, if you are using multiple slots within a component, there is no structured way to pass data through the props, add fallback classes, or use directives. Rather, you will need to pass it all at the component level.

This is not a limitation in terms of functionality but does lead to disorganized code, and can complicate the DX of creating more advanced components.

What does the proposed API look like?

Overview

  • I propose having the ability to pass attributes such as class and href through slots.
  • In the case of attributes such as class, the passed string should be additive.
  • To give the dev full control, these attributes would be applied explicitly within the component using $slots['slotname'].attrs and optionally passing a specific key to attrs such as $slots['slotname'].attrs['class']
  • It should be possible to use v-bind or something similar to apply all of the attributes to a given element
  • It would be ideal to be able to pass props and directives like v-if as well

Example

This example illustrates a possible implementation using a single component (MyComponent.vue) in a page (MyPage.vue) and what the rendered HTML output could look like. It only goes over passing classes since that is the simplest use case, but it would be great if this worked for props and directives as well.

MyComponent.vue

<template>
  <div>
    <h2 class="text-lg" v-bind="$slots['heading'].attrs">
      <slot name="heading" />
    </h2>
    <a class="btn" v-bind="$slots['button'].attrs">
      <slot name="button" />
    </a>
  </div>
</template>

MyPage.vue

<template>
  <MyComponent>
    <template #header class="font-bold">
      This is my heading
    </template>
    <template #button href="/about" class="bg-primary">
      About us
    </template>
  </MyComponent>
</template>

HTML Output

<div>
    <h2 class="text-lg font-bold">
      This is my heading
    </h2>
    <a class="btn bg-primary" href="/about">
      About Us
    </a>
</div>
avatar
Jul 5th 2023

Your case is opposite of mine : https://github.com/vuejs/core/issues/7999. Also I've seen your question on stackoverlfow, let's discuss there in the comments.

avatar
Jul 6th 2023

Your case is opposite of mine : #7999. Also I've seen your question on stackoverlfow, let's discuss there in the comments.

Thank you for sharing :) I am not sure if this is a duplicate exactly, I think we are talking about something very similar, but I would hope the Vue team would consider going beyond just classes and support directives and props as well.

If you agree, please upvote so we can get this feature some attention!