Skip to content

Commit

Permalink
Merge branch 'release/1.2.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
maoberlehner committed May 22, 2018
2 parents 780f96e + 63aa046 commit efa65e3
Show file tree
Hide file tree
Showing 12 changed files with 2,968 additions and 2,703 deletions.
17 changes: 0 additions & 17 deletions .babelrc

This file was deleted.

27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,27 @@ export default {
</script>
```

Or you can pass the module namespace string as the first argument of the `mapFields()` function.

```html
<template>
<div id="app">
<input v-model="foo">
</div>
</template>

<script>
import { mapFields } from 'vuex-map-fields';
export default {
computed: {
// `fooModule` is the name of the Vuex module.
...mapFields(`fooModule`, ['foo']),
},
};
</script>
```

### Multi-row fields

If you want to build a form which allows the user to enter multiple rows of a specific data type with multiple fields (e.g. multiple addresses) you can use the multi-row field mapping function.
Expand Down Expand Up @@ -459,6 +480,12 @@ export default new Vuex.Store({
});
```

## Articles

- [Form Fields, Two-Way Data Binding and Vuex](https://markus.oberlehner.net/blog/form-fields-two-way-data-binding-and-vuex/)
- [How to Handle Multi-row Forms with Vue, Vuex and vuex-map-fields](https://markus.oberlehner.net/blog/how-to-handle-multi-row-forms-with-vue-vuex-and-vuex-map-fields/)
- [How to Structure a Complex Vuex Store](https://markus.oberlehner.net/blog/how-to-structure-a-complex-vuex-store/)

## About

### Author
Expand Down
17 changes: 17 additions & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module.exports = {
presets: [
[
`@babel/preset-env`,
{
modules: false,
},
],
],
env: {
test: {
presets: [
`@babel/preset-env`,
],
},
},
};
5,470 changes: 2,813 additions & 2,657 deletions package-lock.json

Large diffs are not rendered by default.

20 changes: 10 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vuex-map-fields",
"version": "1.1.6",
"version": "1.2.0",
"description": "Enable two-way data binding for form fields saved in a Vuex store",
"keywords": [
"vue",
Expand Down Expand Up @@ -29,18 +29,18 @@
},
"devDependencies": {
"@avalanche/eslint-config": "^2.0.0",
"@babel/core": "^7.0.0-beta.40",
"@babel/preset-env": "^7.0.0-beta.40",
"@vue/test-utils": "^1.0.0-beta.12",
"@babel/core": "^7.0.0-beta.47",
"@babel/preset-env": "^7.0.0-beta.47",
"@vue/test-utils": "^1.0.0-beta.16",
"babel-core": "^7.0.0-bridge.0",
"babel-jest": "^22.4.1",
"coveralls": "^3.0.0",
"eslint": "^4.18.2",
"babel-jest": "^22.4.4",
"coveralls": "^3.0.1",
"eslint": "^4.19.1",
"eslint-plugin-compat": "^2.2.0",
"eslint-plugin-import": "^2.9.0",
"eslint-plugin-import": "^2.12.0",
"eslint-plugin-markdown": "^1.0.0-beta.6",
"jest": "^22.4.2",
"rollup": "^0.56.5",
"jest": "^22.4.4",
"rollup": "^0.59.1",
"rollup-plugin-babel": "^4.0.0-beta.0",
"uglify-es": "^3.3.9",
"vue": "^2.5.16",
Expand Down
34 changes: 30 additions & 4 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
import arrayToObject from './lib/array-to-object';

function normalizeNamespace(fn) {
return (namespace, map, getterType, mutationType) => {
/* eslint-disable no-param-reassign */
if (typeof namespace !== `string`) {
mutationType = getterType;
getterType = map;
map = namespace;
namespace = ``;
} else if (namespace.charAt(namespace.length - 1) !== `/`) {
namespace += `/`;
}

getterType = `${namespace}${getterType || `getField`}`;
mutationType = `${namespace}${mutationType || `updateField`}`;
/* eslint-enable */

return fn(namespace, map, getterType, mutationType);
};
}

export function getField(state) {
return path => path.split(/[.[\]]+/).reduce((prev, key) => prev[key], state);
}
Expand All @@ -15,7 +35,7 @@ export function updateField(state, { path, value }) {
}, state);
}

export function mapFields(fields, getterType = `getField`, mutationType = `updateField`) {
export const mapFields = normalizeNamespace((namespace, fields, getterType, mutationType) => {
const fieldsObject = Array.isArray(fields) ? arrayToObject(fields) : fields;

return Object.keys(fieldsObject).reduce((prev, key) => {
Expand All @@ -34,9 +54,15 @@ export function mapFields(fields, getterType = `getField`, mutationType = `updat

return prev;
}, {});
}
});

export function mapMultiRowFields(paths, getterType = `getField`, mutationType = `updateField`) {
export const mapMultiRowFields = normalizeNamespace((
namespace,
paths,
getterType,
mutationType,
) => {
// export function mapMultiRowFields(paths, getterType = `getField`, mutationType = `updateField`) {
const pathsObject = Array.isArray(paths) ? arrayToObject(paths) : paths;

return Object.keys(pathsObject).reduce((entries, key) => {
Expand Down Expand Up @@ -66,7 +92,7 @@ export function mapMultiRowFields(paths, getterType = `getField`, mutationType =

return entries;
}, {});
}
});

export const createHelpers = ({ getterType, mutationType }) => ({
[getterType]: getField,
Expand Down
61 changes: 61 additions & 0 deletions test/module-namespaced-inline.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import Vuex from 'vuex';
import { createLocalVue, shallowMount } from '@vue/test-utils';

import { mapFields, getField, updateField } from './package/src';

const localVue = createLocalVue();

localVue.use(Vuex);

describe(`Component initialized with namespaced Vuex module.`, () => {
let Component;
let store;
let wrapper;

beforeEach(() => {
Component = {
template: `<input id="foo" v-model="foo">`,
computed: {
...mapFields(`fooModule`, [
`foo`,
]),
},
};

store = new Vuex.Store({
modules: {
fooModule: {
namespaced: true,
state: {
foo: ``,
},
getters: {
getField,
},
mutations: {
updateField,
},
},
},
});

wrapper = shallowMount(Component, { localVue, store });
});

test(`It should render the component.`, () => {
expect(wrapper.exists()).toBe(true);
});

test(`It should update field values when the store is updated.`, () => {
store.state.fooModule.foo = `foo`;

expect(wrapper.element.value).toBe(`foo`);
});

test(`It should update the store when the field values are updated.`, () => {
wrapper.element.value = `foo`;
wrapper.trigger(`input`);

expect(store.state.fooModule.foo).toBe(`foo`);
});
});
5 changes: 2 additions & 3 deletions test/module-namespaced.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Vuex from 'vuex';
import { createLocalVue, shallow } from '@vue/test-utils';
import { createLocalVue, shallowMount } from '@vue/test-utils';

import { createHelpers, getField, updateField } from './package/src';

Expand Down Expand Up @@ -44,7 +44,7 @@ describe(`Component initialized with namespaced Vuex module.`, () => {
},
});

wrapper = shallow(Component, { localVue, store });
wrapper = shallowMount(Component, { localVue, store });
});

test(`It should render the component.`, () => {
Expand All @@ -53,7 +53,6 @@ describe(`Component initialized with namespaced Vuex module.`, () => {

test(`It should update field values when the store is updated.`, () => {
store.state.fooModule.foo = `foo`;
wrapper.update();

expect(wrapper.element.value).toBe(`foo`);
});
Expand Down
5 changes: 2 additions & 3 deletions test/module.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Vuex from 'vuex';
import { createLocalVue, shallow } from '@vue/test-utils';
import { createLocalVue, shallowMount } from '@vue/test-utils';

import { getField, mapFields, updateField } from './package/src';

Expand Down Expand Up @@ -38,7 +38,7 @@ describe(`Component initialized with Vuex module.`, () => {
},
});

wrapper = shallow(Component, { localVue, store });
wrapper = shallowMount(Component, { localVue, store });
});

test(`It should render the component.`, () => {
Expand All @@ -47,7 +47,6 @@ describe(`Component initialized with Vuex module.`, () => {

test(`It should update field values when the store is updated.`, () => {
store.state.fooModule.foo = `foo`;
wrapper.update();

expect(wrapper.element.value).toBe(`foo`);
});
Expand Down
5 changes: 2 additions & 3 deletions test/multi-row.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Vuex from 'vuex';
import { createLocalVue, shallow } from '@vue/test-utils';
import { createLocalVue, shallowMount } from '@vue/test-utils';

import { mapMultiRowFields, getField, updateField } from '../src';

Expand Down Expand Up @@ -48,7 +48,7 @@ describe(`Component initialized with multi row setup.`, () => {
},
});

wrapper = shallow(Component, { localVue, store });
wrapper = shallowMount(Component, { localVue, store });
});

test(`It should render the component.`, () => {
Expand All @@ -58,7 +58,6 @@ describe(`Component initialized with multi row setup.`, () => {
test(`It should update field values when the store is updated.`, () => {
store.state.users[0].name = `New Name`;
store.state.users[1].email = `new@email.com`;
wrapper.update();

expect(wrapper.find(`input`).element.value).toBe(`New Name`);
expect(wrapper.find(`div:nth-child(2) input:nth-child(2)`).element.value).toBe(`new@email.com`);
Expand Down
5 changes: 2 additions & 3 deletions test/nested-store.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Vuex from 'vuex';
import { createLocalVue, shallow } from '@vue/test-utils';
import { createLocalVue, shallowMount } from '@vue/test-utils';

import { createHelpers, getField, updateField } from './package/src';

Expand Down Expand Up @@ -43,7 +43,7 @@ describe(`Component initialized with customized getter and mutation functions.`,
},
});

wrapper = shallow(Component, { localVue, store });
wrapper = shallowMount(Component, { localVue, store });
});

test(`It should render the component.`, () => {
Expand All @@ -52,7 +52,6 @@ describe(`Component initialized with customized getter and mutation functions.`,

test(`It should update field values when the store is updated.`, () => {
store.state.form.foo.foo = `foo`;
wrapper.update();

expect(wrapper.element.value).toBe(`foo`);
});
Expand Down
5 changes: 2 additions & 3 deletions test/packaged.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable import/no-duplicates */
import Vuex from 'vuex';
import { createLocalVue, shallow } from '@vue/test-utils';
import { createLocalVue, shallowMount } from '@vue/test-utils';

import componentFactory from './utils/component';
import storeFactory from './utils/store';
Expand Down Expand Up @@ -65,7 +65,7 @@ localVue.use(Vuex);

beforeEach(() => {
store = storeFactory({ getField, updateField });
wrapper = shallow(Component, { localVue, store });
wrapper = shallowMount(Component, { localVue, store });
});

test(`It should render the component.`, () => {
Expand All @@ -76,7 +76,6 @@ localVue.use(Vuex);
store.state.foo = `foo`;
store.state.bar.bar = `bar`;
store.state.baz[0].foo.baz = `baz`;
wrapper.update();

expect(wrapper.find(`#foo`).element.value).toBe(`foo`);
expect(wrapper.find(`#bar`).element.value).toBe(`bar`);
Expand Down

0 comments on commit efa65e3

Please sign in to comment.