I have an app for which I\'m creating a custom component that will output a single row of a table. It contains a numeric field which is user-adjustable, and so within that c
This is what I ended up with - seemed like the simplest approach. I was kind of hoping Vue would have a mechanism to hide this away when the 'middle' component effectively promises not to change the model, but just wants to hand it on to a child.
Basically, I created an intermediary data element ivalue
, and initialised it in the mounted()
event, and use the input()
event of the child to emit an input()
event back to the parent.
<template>
<tr>
<td class="text-right"><slot></slot></td>
<td class="text-right">
<q-numeric
v-model="ivalue"
:min="min"
:max="max"
:step="step"
@input="$emit('input', ivalue)"
></q-numeric>
</td>
</tr>
</template>
<script>
export default {
data: () => ({
ivalue: 0
}),
mounted () {
this.ivalue = this.value
},
props: {
label: String,
value: Number,
min: {
type: Number,
default: 1
},
max: {
type: Number,
default: 250000
},
step: {
type: Number,
default: 1
}
}
}
</script>
Update: You can propagate v-model
-ability down a hierarchy by making a writable computed based on the prop (the prop must be named 'value'). The get
function obviously returns the prop value; the set
function does the $emit
.
The computed spec is entirely fixed, so I have extracted it as a constant.
const vModelComputed = {
get() {
return this.value;
},
set(newValue) {
this.$emit('input', newValue);
}
};
new Vue({
el: '#app',
data: {
numParticipants: 1
},
components: {
middleComponent: {
props: ['value'],
template: '<div>Value: {{value}} <q-numeric v-model="localValue"></q-numeric></div>',
computed: {
localValue: vModelComputed
},
components: {
qNumeric: {
props: ['value'],
template: '<div><input v-model="localValue" type="number"> inner value: {{value}}</div>',
computed: {
localValue: vModelComputed
}
}
}
}
}
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.2.6/vue.min.js"></script>
<div id="app">
Participants: {{numParticipants}}
<middle-component v-model="numParticipants"></middle-component>
</div>