vue-voodoo-doll

1.0.0-beta.0 • Public • Published

👻 Voodoo Doll

Add props / event-handlers on <voodoo-doll> to proxy them to a distant child component

🙋 Why?

Vue offers provide/inject to communicate with a child component that's passed into a slot. This non-reactive, imperative API might suffice for simple cases, but when data needs to flow bi-directionally or be reactive, you might start to reinvent new ways for components to communicate. This could get messy and pollute your SFC with irrelevant noise.

Voodoo Doll solves this by offering a template API to directly interface with a component outside your SFC! 👻

🚀 Install

npm i vue-voodoo-doll

🔰 Usage JSFiddle Demo

The following demo shows you how to set up a parent-child pair to communicate using Voodoo Doll. Note:

  • The parent uses the <voodoo-doll> component with a secret key to wrap <slot>
    • The Voodoo magic only applies to its children!

  • The child uses the VoodooMixin mixin with the same key to bind to the parent's Voodoo Doll
    • Declare the props array to bind given attributes to the view model context
  • The child can the Voodo via this.$$ (attrs, props, class, listeners)
  • The two components only come together at usage

Usage

<template>
    <div>
        <radio-group v-model="selected">
            <radio label="Apples" value="apples" />
            <radio label="Oranges" value="oranges" />
            <radio label="Bananas" value="bananas" />
        </radio-group>
        <div>
            Selected: {{ selected }}
        </div>
    </div>
</template>
 
<script>
export default {
    data() {
        return {
            selected: [],
        };
    },
};
</script>

Parent: RadioGroup.vue

<template>
    <div>
        <voodoo-doll
            :secret="key"
            :checkedItems="value"
            @update="$emit('input', $event)"
        >
            <slot />
        </voodoo-doll>
    </div>
</template>
 
<script>
import VoodooDoll from 'vue-voodoo-doll';
 
export default {
    components: {
        VoodooDoll,
    },
 
    props: ['value'],
 
    data() {
        return {
            // Same idea as provide/inject
            // Use a Symbol for security
            key: 'radios',
        };
    },
}
</script>

Child: Radio.vue

<template>
    <label>
        <input
            type="checkbox"
            @click="onClick"
            :checked="isChecked"
        >
        {{ label }}
    </label>
</template>
 
<script>
import { VoodooMixin } from 'vue-voodoo-doll';
 
export default {
    mixins: [
        VoodooMixin({
            // Same key as parent
            from: 'radios',
 
            // Declare props that can be voodoo'd in
            // Only array supported for now
            props: ['checkedItems'],
        })
    ],
 
    props: {
        label: String,
        value: null
    },
 
    computed: {
        isChecked() {
            return this.checkedItems.includes(this.value);
        }
    },
 
    methods: {
        onClick() {
            if (this.isChecked) {
                this.$emit('update', this.checkedItems.filter(i => i !== this.value));
            } else {
                this.$emit('update', [...this.checkedItems, this.value]);
            }
        }
    }
};
</script>

👪 Related

  • 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 - 🧬Mutate your vNodes with vNode Syringe 💉

Package Sidebar

Install

npm i vue-voodoo-doll

Weekly Downloads

2

Version

1.0.0-beta.0

License

MIT

Unpacked Size

7.67 kB

Total Files

4

Last publish

Collaborators

  • hirokiosame