Skip to content

Latest commit

 

History

History
265 lines (210 loc) · 6.71 KB

README.md

File metadata and controls

265 lines (210 loc) · 6.71 KB

💉 vNode Syringe Latest version Monthly downloads Install size Bundle size

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

Demo 1: Passing down attributes

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>
Demo 2: Merging and Overwriting classes

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-v - render vNodes via component template
  • vue-frag - 🤲 Directive to return multiple root elements