0.1.1 • Published 5 years ago

vue-vmodel-mapper v0.1.1

Weekly downloads
2
License
MIT
Repository
github
Last release
5 years ago

Vue Vmodel Mapper

vue-vmodel-mapper is a small helper to simplify the creation of custom v-model components that accept an object type as value prop.

Why

It's quite complicated to create custom v-model components that behave correctly, especially if they accept a prop object. The prop cannot be mutated and component must emit a new object on change of any value in the object. You also can't conveniently bind to nested values in prop object using v-model directive since it mutates as well.

vue-vmodel-mapper generates the boilerplate to setup a custom v-model component painlessly by mapping keys in the prop object to computed variables that can detect change and emit a new object with the changes.

Install

npm i --save vue-vmodel-mapper

Basic Usage

<template>
  <input v-model="firstname" />
  <input v-model="lastname" />
</template>
<script>
import vueVmodelMapper from 'vue-vmodel-mapper';

export default {
  name: 'CustomVmodel',
  prop: {
    // value is an object with { firstname, lastname }
    value: {
      type: Object
    }
  },
  computed: {
    // key name for every key in prop object
    ...vueVmodelMapper(['firstname', 'lastname'])
  }
}
</script>

Customize

vue-vmodel-mapper takes two arguments, an array of keys to map into computed variables and an optional customisation object.

Default

Without second argument, vue-vmodel-mapper defaults the v-model prop name to value, and changes will emit event name input.

Custom vmodel event and prop name

Pass a second argument to vue-vmodel-mapper to customize prop and event name to match names used by your component

<template>
  <input v-model="firstname" />
  <input v-model="lastname" />
</template>
<script>
import vueVmodelMapper from 'vue-vmodel-mapper';

export default {
  name: 'CustomVmodel',
  model: {
    prop: 'customKeyName',
    event: 'customEventName'
  },
  prop: {
    // value is an object with { firstname, lastname }
    value: {
      type: Object
    }
  },
  computed: {
    ...vueVmodelMapper(
      ['firstname', 'lastname'],
      {
        prop: 'customKeyName',
        event: 'customEventName'
      }
    )
  }
}
</script>

How it works

Create computed variables for every key in this.value with separate get and set functions. Setting a computed variable will trigger an emit of a new object instead of mutating the existing this.value prop.

vue-vmodel-mapper is just a helper generates the computed variables below.

<template>
  <input v-model="firstname">
  <input v-model="lastname">
</template>
<script>
export default {
  name: 'CustomVmodel',
  prop: {
    value: {
      type: Object
    }
  },
  // boilerplate generated by vue-vmodel-mapper
  computed: {
    firstname: {
      get() {
        return this.value.firstname;
      },
      // setter to emit new object on change of firstname
      set(newValue) {
        this.$emit('input', {
          ...this.value,
          firstname: newValue,
        });
      }
    },
    lastname: {
      get() {
        return this.value.lastname;
      },
      // setter to emit new object on change of lastname
      set(newValue) {
        this.$emit('input', {
          ...this.value,
          lastname: newValue,
        });
      }
    }
  }
}
</script>

Caveats

It assumes values for the object keys mapped are primitive types like String, Number or Boolean. It cannot detect changes in nested objects.

eg:

// can't detect changes to innerkey1
const prop = {
  key1: 'hello',
  key2: {
    innerkey1: 'world'
  }
}

Running tests

npm i
npm test
npm run test:watch