is it possible to set attributes on a slot and the element from the parent gets these attributes?
Parent
<vDropdown>
<button slot="button">new button</button>
<ul>content</ul>
</vDropdown>
Dropdown.vue
<div>
<slot name="button" aria-haspopup="true">
//fallback
<button aria-haspopup="true">Default Button</button>
</slot>
<div id="name" :aria-expanded="expanded">
<slot />
</div>
</div>
the output for the button is without any attributes...
<div>
<button>new button</button>
<div id="myDropdown" aria-expanded="false">
<ul>content</ul>
</div>
</div>
Use Scoped Slots
Step 1. In the parent, update the old deprecated slot targeting syntax slot="button"
to the v-slot
directive:
Parent.vue
...
<template v-slot:button> ✅
<button>new button</button>
</template>
...
<button slot="button">new button</button> ❌
How to target a slot in Vue 2.6.0+
Step 2. Next, understand that any attribute bindings you add to a <slot>
tag will become available to any slotted content placed there (these are called "slot props"):
Dropdown.vue
<slot name="button" :aria-haspopup="true">
Step 3. Vue automatically creates an object containing every binding from Step 2, and passes that to the v-slot
expression, i.e. slotProps
below. You can then use the special v-bind=""
syntax to spread all those bindings onto the button:
Parent.vue updated
<template v-slot:button="slotProps">
<button v-bind="slotProps">new button</button>
</template>
Here's a demo, but sadly it requires a hack using two hyphens when you do this with a kebab-case attribute. I'll plan to submit an issue for this in the Vue GitHub repo.
Vue.component('dropdown', {
template: `
<div>
<slot name="button" aria--haspopup="true">
<button aria-haspopup="true">Default Button</button>
</slot>
<div id="name" :aria-expanded="expanded">
<slot />
</div>
</div>`,
data() {
return {
expanded: true
}
}
});
new Vue({
el: "#app",
});
.aria-haspopup {
background: orange;
}
<div id="app">
<dropdown>
<template v-slot:button="slotProps">
<button v-bind="slotProps">new button</button>
</template>
<ul>content</ul>
</dropdown>
</div>
<script src="https://unpkg.com/vue"></script>