Sign Up for Free

RunKit +

Try any Node.js package right in your browser

This is a playground to test code. It runs a full Node.js environment and already has all of npm’s 400,000 packages pre-installed, including vuex-dot with all npm packages installed. Try it out:

var vuexDot = require("vuex-dot")

This service is provided by RunKit and is not affiliated with npm, Inc or the package authors.

vuex-dot v2.5.8

Simplifies two-way data binding and v-model usage on vuex state, providing full reactivity via generated setters/getters

vuex-dot tests Coverage Status GitHub license minified bundle

Codepen demo

Vue computed properties getters and/or setters generator with the ability to intercept each property change and dispatch vuex action or commit mutation or just hook your own callback. Also you can use plugins.

The main idea of this tool is to have mapState()-like helper with an ability to set additional configuration using chainable methods.

Motivation

There are some other packages on github - vuex-map-fields and vuex-bound for example, but after reading their docs and sources I've decided to create own package from scratch with such benefits

  • lightweight - 3.41 KB after rollup && babel-minify
  • flexible - actions dispatching and hooks abilities adds to your code one place for handling reactive changes of target. Plugins support gives you full control of your data flow.
  • simple - less code footprint with same features. You need to import only one helper method into your code, which provides a short set of chainable methods for configuring.
  • no foreign code injection to your state - no weird logic ("core" mutations, actions, etc) shall be injected into your vuex store, no additional setup of vuex or vm needed. This tool just generates getters and setters, which are done with performance in mind.
  • dot notation - with usage of very fast and well tested library get-value

Installation

npm i vuex-dot

Usage

State property two way binding (mutation based)

https://codepen.io/anon/pen/ERmBqK

Target.commit(action)

<template>
  <button @click.stop="step++">next</button>
</template>

<script>
  import { takeState } from 'vuex-dot';

  export default {
    computed: {
      step: takeState('wizard.step') 
        .commit('setWizardStep')
        .map()
    }
  }
</script>

store/index.js

export default new Vuex.Store({
  state: {
    wizard: {
      step: 1
    }
  },
  mutations: {
    setWizardStep(state, step) {
      state.wizard.step = step;
    }
  }
});

Target selected object fields exposition (action based)

https://codepen.io/anon/pen/eKWqOm

<template>
  <form>
    <input v-model="name"/>
    <input v-model="email"/>
  </form>
</template>

<script>
  import { takeState } from 'vuex-dot';

  export default {
    computed: {
      ...takeState('user')
        .expose(['name', 'email'])
        .dispatch('editUser')
        .map()
    }
  }
</script>

Exposed target hook usage

<template>
  <form>
    <input v-model="name"/>
    <input v-model="email"/>
  </form>
</template>

<script>
  import { takeState } from 'vuex-dot';
  import validate from 'validate';
  const constraints = {name: {presence: true}}; 

  export default {
    computed: {
      ...takeState('user')
        .expose([
          'name', 
          'email'
        ])
        .hook(({ dispatch }, value, key) => {
          if(validate.single(value, constraints[key])) {
            dispatch('userEditAction', { key, value });
          }
        })
        .map()
    }
  }
</script>

API reference

Classes

Target

Target mapper

TargetExposition

Exposes some properties of target object into computed properties compatible bunch of getters or/and setters

Functions

take(path)Target

returns Target instance with specified path

takeState(namespace, path)Target

returns Target instance with specified state path

Target

Target mapper

new Target(path)

ParamTypeDescription
pathstringdot-notation path to some property of your vm instance

target.expose(projection) ⇒ TargetExposition

Should be used if you need to map some properties of the object, selected as a target into your computed properties. It allows to attach action dispatcher or hook callback on each property change.

Also, both dispatch() and hook() can provide object mapped by Target instance to the callee, while setting the second argument true (you can read more in the documentation for them)

ParamTypeDescription
projectionarraytarget object properties to be exposed

target.commit(mutation) ⇒ Target

In fact, that's syntax sugar for hook() method.

Sets mutation to be commited on mapped property change

mutation shall be called in the format:

commit(mutation, newValue)

ParamTypeDescription
mutationstringmutation name

target.dispatch(action) ⇒ Target

In fact, that's syntax sugar for hook() method.

Sets action to be dispatched on mapped property change

Your action shall be called in the format:

dispatch(action, newValue)

ParamTypeDescription
actionstringaction name

target.hook(dispatcher) ⇒ Target

Set hook that should be run on mapped property change.

ParamType
dispatcherdispatcher

target.map(alias) ⇒ *

returns computed property pair of getters or/and setters for specified projection.

If an alias is set, it can be used with spread operator setting provided alias as the computed property name

ParamTypeDescription
aliasStringname of computed field target to be accessible

target.use(plugin) ⇒ Target

apply plugin

plugin is described by object, composed in such format:

{
  setter: function(key, value, nextSetter) { //setter is mandatory
    nextSetter(value);
  },
  getter: function(key, nextGetter) { //getter is optional
    return nextGetter();
  },
  inject: { // optional, here you can describe additional fields, you want to inject into result map
    $internal: {
      get() { ... },
      set(value) { ... }
    }
  }
}
ParamTypeDescription
pluginObjectobject, describing your plugin.

Target~dispatcher : function

ParamTypeDescription
storeStorevuex store
valuemixed

TargetExposition

Exposes some properties of target object into computed properties compatible bunch of getters or/and setters

new TargetExposition(target, projection)

ParamType
targetTarget
projectionArray

targetExposition.commit(mutation, sendTarget) ⇒ TargetExposition

Sets mutation to be commited on exposed field change if sendTarget is false, action shall be called in format:

commit(mutation, { key, value })

otherwise, if sendTarget is set to true

commit(mutation, { target, key, value })

Hint: That's just syntax sugar for hook() method.

ParamTypeDefaultDescription
mutationStringname of mutation
sendTargetBooleanfalsesend target to action

targetExposition.dispatch(action, sendTarget) ⇒ TargetExposition

Sets action to be dispatched on exposed field change. if sendTarget is false, action shall be called in format:

dispatch(action, { key, value })

otherwise, if sendTarget is set to true

dispatch(action, { target, key, value })

Hint: That's just syntax sugar for hook() method.

ParamTypeDefaultDescription
actionStringname of action
sendTargetBooleanfalsesend target to action

targetExposition.hook(dispatcher, sendTarget) ⇒ TargetExposition

set callback to be run on property change

ParamType
dispatcherdispatcher
sendTargetBoolean

targetExposition.map() ⇒ Object

generates map of getters or/and setters for specified projection

targetExposition.use(plugin) ⇒ TargetExposition

look Target.use(plugin)

Param
plugin

TargetExposition~dispatcher : function

ParamTypeDescription
storeStorevuex store
value*changed value
keyStringkey of changed field
target*parent object of changed field

take(path) ⇒ Target

returns Target instance with specified path

ParamTypeDescription
pathstringdotted path to target property of your component instance

takeState(namespace, path) ⇒ Target

returns Target instance with specified state path

Param
namespace
path
RunKit is a free, in-browser JavaScript dev environment for prototyping Node.js code, with every npm package installed. Sign up to share your code.
Sign Up for Free