vue-vnode-syringe
v3.1.1
Published
Add attributes and event-listeners to <slot> content
Downloads
871
Maintainers
Readme
:syringe: vNode Syringe
Add attributes and event-listeners to <slot>
content.
Supports key
, class
/style
, attrs
, props
& listeners
!
<template>
<div>
<vnode-syringe
class="new-class"
@click="handleClick"
>
<slot /> ⬅ The class and event-listener gets added to every element passed in
</vnode-syringe>
</div>
</template>
🙋♂️ Why?
- 🔥 Set or overwrite attributes & event-listeners on content received from the
<slot>
! - 🧠 Smart merging strategies Pick between merging, overwriting, or falling-back!
- 🐥 Tiny
1.05 KB
minzipped!
🚀 Install
npm i vue-vnode-syringe
💠 Merging strategies
Fallback
This is the default behavior. The class new-class
and event-listener newOnClick
only gets added if there isn't one added yet.
<vnode-syringe
class="new-class"
@click="newOnClick"
>
<slot />
</vnode-syringe>
For example, given the following <slot>
content, only the event-listener newOnClick
will be added:
<div
class="some-class"
<!-- @click="newOnClick" gets added -->
>
some content
</div>
Overwrite !
Add !
at the end of the attribute or event-listener to overwrite what exists.
<vnode-syringe
class!="new-class"
@click!="newOnClick"
>
<slot />
</vnode-syringe>
For example, given the following <slot>
content, both the class and event-listener will overwrite the existing class and event-listener.
<div
class="some-class" <!-- becomes "new-class" -->
@click="existing" <!-- becomes "newOnClick" -->
>
some content
</div>
Merge &
Add &
at the end of the attribute or event-listener to merge with what exists.
<vnode-syringe
class&="new-class"
@click&="newOnClick"
>
<slot />
</vnode-syringe>
For example, given the following <slot>
content, both the class and event-listener will merge with the existing class and event-listener. When merging event-listeners, both event-listeners will be called.
<div
class="some-class" <!-- becomes "some-class new-class" -->
@click="existing" <!-- becomes "existing(); newOnClick()" -->
>
some content
</div>
👨🏻🏫 Examples
In this demo, the class="button-group__button"
attribute is passed down to all of its <slot>
content.
ButtonGroup.vue
<template>
<div class="button-group">
<vnode-syringe
class="button-group__button"
>
<slot />
</vnode-syringe>
</div>
</template>
<style scoped>
.button-group { ... }
.button-group__button { ... }
</style>
Usage.vue
<button-group>
<button>Button 1</button> <!-- Will render with the `button-group__button` class -->
<button>Button 2</button> <!-- Will render with the `button-group__button` class -->
<button>Button 3</button> <!-- Will render with the `button-group__button` class -->
</button-group>
By default, vNode Syringe only adds the attribute/event-listener if it doesn't already exist. To merge with or overwrite the existing one, use the &
(merge) or !
(overwrite) suffix.
ButtonGroup.vue
<template>
<div class="button-group">
<vnode-syringe
<!-- Merge with existing class -->
class&="button-group__button"
<!-- Force all buttons to have type="button" -->
type!="button"
<!-- Only gets added if child doesn't specify `disabled` -->
:disabled="disabled"
>
<slot />
</vnode-syringe>
</div>
</template>
<script>
export default {
props: {
disabled: Boolean
}
};
</script>
<style scoped>
.button-group { ... }
.button-group__button { ... }
</style>
Usage.vue
<button-group disabled>
<button
<!-- Gets overwritten to button button-group__button -->
class="button"
<!-- Gets overwritten to type="button" -->
type="submit"
<!-- Will be inherit parent's disabled state -->
>
Button 1
</button>
<button
<!-- Gets overwritten to button button-group__button -->
class="button"
<!-- Won't inherit parent's disabled state -->
:disabled="false"
>
Button 2
</button>
</button-group>
💁♀️ FAQ
How can I add attributes/event-listeners to a specific element in the <slot>
?
You can use Subslot to pick out specific elements in the slot.
For example, if you only want to accept <button>
s in your slot:
<template>
<div class="button-group">
<vnode-syringe
class&="button-group-item"
@click="onClick"
>
<subslot element="button" />
</vnode-syringe>
</div>
</template>
<script>
import Subslot from 'vue-subslot';
import vnodeSyringe from 'vue-vnode-syringe';
export default {
components: {
Subslot,
vnodeSyringe
},
...,
methods: {
onClick() {
...
}
}
};
</script>
👨👩👧 Related
- vue-proxi - 💠 Tiny proxy component
- vue-subslot - 💍 Pick 'n choose what you want from a slot passed into your Vue component
- vue-pseudo-window - 🖼 Declaratively interface window/document in your Vue template
- vue-vnode-syringe - render vNodes via component template
- vue-frag - 🤲 Directive to return multiple root elements