vuex-dot
vuex-dot copied to clipboard
Question: Handle arrays properly
Hi,
what is the best way to expose items of arrays? store/index.js
export const state = () => {
foo: [
{ bar_1: { attr: 'change me' } }
, { bar_2: { attr: 'change me 2' } }
]
}
export const mutations = {
do_something (state, { key, value }) {
// how to handle this properly???
}
page/foo.vue
<template>
<input v-model = 'bar_1.attr'/>
<input v-model = 'bar_2.attr'/>
</template>
<script>
export default {
computed: {
...takeState('foo')
.expose( ??? )
.commit('do_soemthing')
.map()
}
}
</script>
I would like to expose all attr attributes of the items, namespaced by bar_1 and bar_2. Or at least expose bar_1 and bar_2. Could you help me please with this and show (a) possible solution(s)? Would be great. But I don't want to handle this one by one, instead I would like to pass and handle the array at once and get all the getters and setters for each item in the array.
Hi, in such situation i create component, to which item via props is passed, using v-for.
and, after that, you can expose your item using take()
(not takeState
)
Foo.vue
<template>
<bar-edit :bar="bar" v-for="bar in foo" />
</template>
<script>
export default {
computed: {
...mapState(['foo']);
}
}
</script>
BarEdit.vue
<template>
<input v-model = 'attr'/>
</template>
<script>
export default {
props: ['bar']
computed: {
...take('bar')
.expose( [ 'attr' ] )
.commit('do_something')
.map()
}
}
</script>
Thank you for your quick response! Looks like a reasonable approach. Thank you for that and please keep going with this good work :+1: I'll use it know in my projects :smile:
Just one more question. It seems to be vue specific. I want to pass all attributes as props, but it seems that in computed propertys this is not available?!. Can you tell me what I'm missing?
components/form-item.vue
export default {
props: {
item: {
type: Object
, required: true
}
, attribute: {
type: Array
, default: () => ['value']
}
, commit: {
type: String
}
}
/*
, computed: {
...take(this.item)
.expose(this.attribute)
.commit(this.commit)
.map()
} // not working
*/
, computed: {
...take('item')
.expose(['value'])
.commit('do_soemthing')
.map()
} // is working
}
components/form.vue
<template>
<formItem
commit = 'do_something'
:item = 'item'
attribute = 'value'
/>
</template>
<script>
import formItem from './form-item'
export default {
data () {
return {
item: this.$store.state.form[0]
}
, components: {
formItem
}
}
</script>
I'm a bit confused, could you help me please to see the picture? :smiley: Why can't I just pass the props to your function?
Solved some parts. Who is able to read, has a clear advantage. (german saying) ^^ In the docu about vuex is written:
// in full builds helpers are exposed as Vuex.mapState
import { mapState } from 'vuex'
export default {
// ...
computed: mapState({
// arrow functions can make the code very succinct!
count: state => state.count,
// passing the string value 'count' is same as `state => state.count`
countAlias: 'count',
// to access local state with `this`, a normal function must be used
countPlusLocalState (state) {
return state.count + this.localCount
}
})
}
https://vuex.vuejs.org/guide/state.html#the-mapstate-helper
If you want to use this you need to use a function...
I did this an it worked:
Who is able to read, has a great advantage (german saying) :smiley: In vuex docs is written:
// in full builds helpers are exposed as Vuex.mapState
import { mapState } from 'vuex'
export default {
// ...
computed: mapState({
// arrow functions can make the code very succinct!
count: state => state.count,
// passing the string value 'count' is same as `state => state.count`
countAlias: 'count',
// to access local state with `this`, a normal function must be used
countPlusLocalState (state) {
return state.count + this.localCount
}
})
}
You need to use a function to access this https://vuex.vuejs.org/guide/state.html#the-mapstate-helper
I did this and it worked: components/formItem
export default {
computed: {
...take(state => { return this.item }) // this is the trick
.expose(['value']) // unfortunately not working here .expose(state => { return this.attribute })
.commit('do_something', arguments) // nore does it here but nice feature?!
.map()
}
}
If I pass a secend arguement to so commit function, I get the target as parameter in the mutation and so you are able to mutate the state over this parameter. This is quite usefull, if you don't know where the exact subtree of the state belongs to. For example my store looks like this:
export const state = () => {
foo: {
bar: {
form: [ ] // some Objects
}
}
, foo_2: {
bar_2: {
form: [ ] // more Objects
}
}
}
export const mutations = {
do_something (state, payload) {
console.log('vuex payload ', payload)
payload.target.item.value = payload.value
}
}
If I pass via props this.$store.state.foo.bar.form I don't know in the component, where the form belongs to. It could be foo.bar or foo_2.bar_2. But with the target parameter, I can mutate the right values. I'm not sure if this is supposed to do so. Doesn't feel well. :confused:
Here you can see the target attribute. In target.item is my state I want to handle. I can change the value in the mutation without complains from vuex, that I should not mutate state directly. But it feels strange.