Versions:
i try to use vuex with el-input
the problem is i dont use a v-model because i cant mutate state outside from a mutation(strict)
<el-input
:value="item.description"
@input="update($event, 'description', index)"
type="textarea"
:autosize="{ minRows: 1, maxRows: 4}"
placeholder="Please input">
</el-input>
update(e, field, index) {
this.$store.commit('UPDATE_INVOICE_ARTICLE', { index, value: e.target.value, field })
}
// Mutation
[types.UPDATE_INVOICE_ARTICLE] (state, article) {
var newValue = { [article.field]: article.value }
Object.assign(state.invoiceArticles[ article.index ], newValue)
},
This works
<input type="text" :value="item.description" @input="update($event, 'description',index)">
vue.runtime.common.js?d43f:511 [Vue warn]: Error in watcher "currentValue"
(found in component <ElInput>)
Create.vue?71c5:233 Uncaught (in promise) TypeError: Cannot read property 'value' of undefined
at VueComponent.update (eval at <anonymous> (client.js:1330), <anonymous>:236:83)
at Proxy.boundFn (eval at <anonymous> (client.js:730), <anonymous>:125:14)
at Object.input [as fn] (eval at <anonymous> (client.js:1588), <anonymous>:35:15)
at VueComponent.eval (eval at <anonymous> (client.js:730), <anonymous>:2186:16)
at VueComponent.Vue.$emit (eval at <anonymous> (client.js:730), <anonymous>:3183:16)
at VueComponent.currentValue (eval at <anonymous> (client.js:1393), <anonymous>:3002:13)
at Watcher.run (eval at <anonymous> (client.js:730), <anonymous>:1709:19)
at flushSchedulerQueue (eval at <anonymous> (client.js:730), <anonymous>:1513:13)
at Array.eval (eval at <anonymous> (client.js:730), <anonymous>:376:20)
at nextTickHandler (eval at <anonymous> (client.js:730), <anonymous>:326:16)
or i just do it wrong
thx! awesome ui
@input="update($event, 'description', index)"
first param of the input event handler is exactly the input current value instead of a event.
update(value, field, index) {
this.$store.commit('UPDATE_INVOICE_ARTICLE', { index, value, field })
}
thx but this is undefined for me but the error is gone
this is what i have now from your example
```
<el-input
:value="item.description"
@input="update(val,'description', index)"
type="textarea"
:autosize="{ minRows: 1, maxRows: 4}"
placeholder="Please input"
>
update(val, field, index) {
//const newValue = this.invoiceArticles[ index ]
console.log(val) //undefined
```
You can use watch
a object to chang v-model mutation
watch:{
"item.description":{
handler(newVal){
this.$store.commit(....)
}
}
}
The advantage is that if you have multiple attributes to commit
"item":{
handler(newVal){
if(newVal.description){
//TODO
}
if(newVal.name){
//TODO
}
this.$store.commit(....)
}
}
i don't like use @input
in vm to vuex
update(e, field, index) {
this.$store.commit('UPDATE_INVOICE_ARTICLE', { index, value: e, field })
}
@input
return value not 'event', or you can use @input.native
@QingWei-Li inpute.native works the other not i have no idea why
@yelingfeng i tried to watch but i cant see any changes
I have this and each item has multiple fields
<tr v-for="(item,index) in invoiceArticles" :key="item.id"> //invoiceArticles is from the vuex getter in a computed prop
..table stuff
<el-input
:value="item.description"
@input.native="update($event,'description', index)"
type="textarea"
:autosize="{ minRows: 1, maxRows: 4}"
placeholder="Please input"
>
</el-input>
.. more fields (item.price,...)
//Watch i cant see any changes
watch: {
'invoiceArticles': {
handler(newval) {
console.log('hehehe')
}
}
},
@yelingfeng i updated
this works but i cant use if to determine which is changed
watch: {
'invoiceArticles': {
handler(newVal) {
console.log(newVal)
if (newVal.description) {
console.log(newval) //second problem when i have more than 1 item i get the whole array^^
}
},
deep: true,
}
},
/e ### I have a new IDEA i try to split i will tell you it does work or not xD
So i just splitted every row in a single component file
then on beforeMount i just make a deepClone maybe i can just use Object.assign i will later check
then i use v-model again and on update i update my clonedObject in the vuex store
thx
<style lang="sass" rel="stylesheet/scss">
</style>
<template>
<tr>
<td style="width: 20px;">
<strong>{{pos+1}}.</strong>
</td>
<td class="table-name" style="width: 400px;">
<el-input
v-model="ownItem.name"
@input="update"
type="textarea"
:autosize="{ minRows: 1, maxRows: 4}"
placeholder="Please input">
</el-input>
</td>
<td class="table-price" style="width: 150px;">
<el-input @input="update" v-model="ownItem.price" :min="0">
</el-input>
</td>
<td class="table-qty" style="width: 100px;">
<el-input-number @input="update" v-model="ownItem.qty" :min="0"></el-input-number>
</td>
<td class="table-total">
<span class="table-text">{{ownItem.qty * ownItem.price | formatMoney}}</span>
</td>
<td class="table-remove">
<el-button type="danger" size="small" @click="removeArticle(index)"
icon="delete"></el-button>
</td>
</tr>
</template>
<script>
import { cloneDeep } from 'lodash'
export default {
computed: {
ownItem() {
return Object.assign({}, this.item)
}
},
name: 'InvoiceArticle',
props: {
item: {
required: true,
type: Object
},
pos: {
required: true,
type: Number
}
},
data() {
return {
ownItem: {}
}
},
methods: {
update() {
this.$store.commit('UPDATE_INVOICE_ARTICLE', { index: this.pos, item: this.ownItem })
}
}
}
</script>
I have this same issue. If you use :value you can't update the input (literally typing in the field). V-model is just not an option when using vuex. Vue's default behavior allows you to update the input value when using :value, so it's weird that this behavior would change.
I found the discussion in this issue very difficult to understand. From my experience it seems that:
$event
contains the literal content of the text field, not the DOM event. And you can use that to update your store. Just don't try $event.target.value
because there's no such field.:value
does work and will react to value changes that are done in the store. AFAICS there's no need for manual watches.
Most helpful comment
I have this same issue. If you use :value you can't update the input (literally typing in the field). V-model is just not an option when using vuex. Vue's default behavior allows you to update the input value when using :value, so it's weird that this behavior would change.