1
0
mirror of synced 2025-02-16 20:53:13 +03:00

Fixes an insideous bug that was causing vuex mutations in deeply linked prop data

This commit is contained in:
Justin Schroeder 2018-02-02 12:07:51 -05:00
parent b061bda3a2
commit 8efe308f98
8 changed files with 158 additions and 15 deletions

View File

@ -57,14 +57,20 @@ root store:
**Root Store** **Root Store**
```js ```js
import {formulateState, formulateGetters, formulateMutation} from 'vue-formulate' import Vue from 'vue'
import Vuex from 'vuex'
import {formulateState, formulateGetters, formulateMutations} from 'vue-formulate'
Vue.use(Vuex)
const state = () => ({ const state = () => ({
// your own state data can live next to vue-formulate's data
your: 'data', your: 'data',
...formulateState() ...formulateState()
}) })
const getters = { const getters = {
// Your own getters can live next to vue-formulate's getters
yourGetter (state) { yourGetter (state) {
return state.your return state.your
}, },
@ -72,17 +78,18 @@ const getters = {
} }
const mutations = { const mutations = {
// Your own mutations can live next to vue-formulate's mutations
setYour (state, payload) { setYour (state, payload) {
state.your = payload state.your = payload
}, },
...formulateMutations() ...formulateMutations()
} }
export default { export default new Vuex.Store({
state, state,
getters, getters,
mutations mutations
} })
``` ```
### Usage ### Usage

44
dist/index.js vendored

File diff suppressed because one or more lines are too long

88
package-lock.json generated
View File

@ -1943,6 +1943,32 @@
"wordwrap": "0.0.2" "wordwrap": "0.0.2"
} }
}, },
"clone-deep": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-3.0.1.tgz",
"integrity": "sha512-kWn5hGUnIA4algk62xJIp9jxQZ8DxSPg9ktkkK1WxRGhU/0GKZBekYJHXAXaZKMpxoq/7R4eygeIl9Cf7si+bA==",
"requires": {
"for-own": "1.0.0",
"is-plain-object": "2.0.4",
"kind-of": "6.0.2",
"shallow-clone": "2.0.2"
},
"dependencies": {
"for-own": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz",
"integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=",
"requires": {
"for-in": "1.0.2"
}
},
"kind-of": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
"integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="
}
}
},
"co": { "co": {
"version": "4.6.0", "version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
@ -3053,8 +3079,7 @@
"for-in": { "for-in": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
"integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA="
"dev": true
}, },
"for-own": { "for-own": {
"version": "0.1.5", "version": "0.1.5",
@ -4587,6 +4612,21 @@
"integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=",
"dev": true "dev": true
}, },
"is-plain-object": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
"integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
"requires": {
"isobject": "3.0.1"
},
"dependencies": {
"isobject": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
}
}
},
"is-posix-bracket": { "is-posix-bracket": {
"version": "0.1.1", "version": "0.1.1",
"resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz",
@ -5163,6 +5203,25 @@
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
"dev": true "dev": true
}, },
"mixin-object": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-3.0.0.tgz",
"integrity": "sha512-RsUqTd3DyF9+UPqhLzJIWwGm4ZGIPYOu6WcQhQuBqqVBGhc6LOC8LrFk9KD7PvVwmqri45IJT88WLrNNrMWjxg==",
"requires": {
"for-in": "1.0.2",
"is-extendable": "1.0.1"
},
"dependencies": {
"is-extendable": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
"integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
"requires": {
"is-plain-object": "2.0.4"
}
}
}
},
"mkdirp": { "mkdirp": {
"version": "0.5.1", "version": "0.5.1",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
@ -6303,6 +6362,31 @@
"safe-buffer": "5.1.1" "safe-buffer": "5.1.1"
} }
}, },
"shallow-clone": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-2.0.2.tgz",
"integrity": "sha512-2o81AG/RpLTAG/ZXQekPtH/6yTffzKlJ+i6UhtVTtnP6zWQaNo9vt6LI28bhZLSesB12VQSfJYtXopTogVBveg==",
"requires": {
"is-extendable": "1.0.1",
"kind-of": "6.0.2",
"mixin-object": "3.0.0"
},
"dependencies": {
"is-extendable": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
"integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
"requires": {
"is-plain-object": "2.0.4"
}
},
"kind-of": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
"integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="
}
}
},
"shebang-command": { "shebang-command": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",

View File

@ -59,6 +59,7 @@
] ]
}, },
"dependencies": { "dependencies": {
"clone-deep": "^3.0.1",
"shortid": "^2.2.8" "shortid": "^2.2.8"
} }
} }

View File

@ -9,6 +9,7 @@
<script> <script>
import {equals} from '../utils' import {equals} from '../utils'
import cloneDeep from 'clone-deep'
export default { export default {
props: { props: {
@ -49,7 +50,7 @@ export default {
return this.$store.getters[`${this.m}hasErrors`][this.name] || false return this.$store.getters[`${this.m}hasErrors`][this.name] || false
}, },
values () { values () {
return this.$store.getters[`${this.m}formValues`][this.name] || {} return cloneDeep(this.$store.getters[`${this.m}formValues`][this.name] || {})
}, },
errors () { errors () {
return this.$store.getters[`${this.m}formErrors`][this.name] || {} return this.$store.getters[`${this.m}formErrors`][this.name] || {}
@ -79,9 +80,10 @@ export default {
methods: { methods: {
registerField (field, data) { registerField (field, data) {
this.$store.commit(`${this.m}setFieldMeta`, {form: this.name, field, data}) this.$store.commit(`${this.m}setFieldMeta`, {form: this.name, field, data})
this.updateFormValidation()
}, },
hydrate (values) { hydrate (values) {
for (let field of this.fields) { for (let field in this.fields) {
if (field.type !== 'submit') { if (field.type !== 'submit') {
this.$store.commit(`${this.m}setFieldValue`, { this.$store.commit(`${this.m}setFieldValue`, {
field: field.name, field: field.name,

View File

@ -97,7 +97,7 @@
</template> </template>
<script> <script>
import {inputTypes, equals, reduce} from '../utils' import {inputTypes, equals, reduce, filter} from '../utils'
import shortid from 'shortid' import shortid from 'shortid'
export default { export default {
@ -197,11 +197,10 @@ export default {
if (value === undefined) { if (value === undefined) {
switch (this.type) { switch (this.type) {
case 'color': case 'color':
value = '#000000' return '#000000'
break
case 'checkbox': case 'checkbox':
if (this.optionList.length > 1) { if (this.optionList.length > 1) {
value = [] return []
} }
break break
} }
@ -279,7 +278,10 @@ export default {
} }
}, },
created () { created () {
this.form.registerField(this.name, this.$props) this.form.registerField(
this.name,
filter(this.$props, (prop, value) => ['name', 'type', 'id', 'label', 'validation'].includes(prop)),
)
if (this.initial !== false) { if (this.initial !== false) {
this.form.hydrate({[this.name]: this.initial}) this.form.hydrate({[this.name]: this.initial})
} }

View File

@ -27,7 +27,10 @@ export const formulateGetters = (moduleName = '', getters = {}) => Object.assign
return state.validationErrors return state.validationErrors
}, },
formMeta (state) { formMeta (state) {
return map(state.meta, (form, fields) => Object.entries(fields).map(([key, value]) => value)) return reduce(state.meta, (forms, form, fields) => {
forms[form] = reduce(fields, (arr, field, data) => arr.concat(data), [])
return forms
}, {})
}, },
hasErrors (state) { hasErrors (state) {
return map(state.errors, (form, errors) => { return map(state.errors, (form, errors) => {

View File

@ -1,3 +1,5 @@
import cloneDeep from 'clone-deep'
/** /**
* Compare the equality of two arrays. * Compare the equality of two arrays.
* @param {Array} arr1 * @param {Array} arr1
@ -20,7 +22,7 @@ export function equals (arr1, arr2) {
* @param {Function} callback * @param {Function} callback
*/ */
export function map (original, callback) { export function map (original, callback) {
let obj = Object.assign({}, original) let obj = cloneDeep(original)
for (let key in obj) { for (let key in obj) {
obj[key] = callback(key, obj[key]) obj[key] = callback(key, obj[key])
} }