Skip to content

tools for state mapping to computed with smooth and flexible v-model support

License

Notifications You must be signed in to change notification settings

yarsky-tgz/vuex-dot

Repository files navigation

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)

Param Type Description
path string dot-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)

Param Type Description
projection array target 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)

Param Type Description
mutation string mutation 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)

Param Type Description
action string action name

target.hook(dispatcher) ⇒ Target

Set hook that should be run on mapped property change.

Param Type
dispatcher dispatcher

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

Param Type Description
alias String name 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) { ... }
    }
  }
}
Param Type Description
plugin Object object, describing your plugin.

Target~dispatcher : function

Param Type Description
store Store vuex store
value mixed

TargetExposition

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

new TargetExposition(target, projection)

Param Type
target Target
projection Array

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.

Param Type Default Description
mutation String name of mutation
sendTarget Boolean false send 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.

Param Type Default Description
action String name of action
sendTarget Boolean false send target to action

targetExposition.hook(dispatcher, sendTarget) ⇒ TargetExposition

set callback to be run on property change

Param Type
dispatcher dispatcher
sendTarget Boolean

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

Param Type Description
store Store vuex store
value * changed value
key String key of changed field
target * parent object of changed field

take(path) ⇒ Target

returns Target instance with specified path

Param Type Description
path string dotted path to target property of your component instance

takeState(namespace, path) ⇒ Target

returns Target instance with specified state path

Param
namespace
path

About

tools for state mapping to computed with smooth and flexible v-model support

Resources

License

Stars

Watchers

Forks

Packages

No packages published