Reputation: 8047
I have a basic component for all my input fields that wraps a dynamic component.
<my-input v-model="book_id" as="select" :options="availableBooks"
label="Books" :dirty="changed.includes('book_id')"/>
I use a computed property to feed that component.
availableBooks () {
if(this.books.length === 0) {
return [{id: '1', text: 'test1'}]
} else {
return [{id: '2', text: 'test2'}]
}
}
Inside my-input component, I render dynamically a component /my-input.vue
<template>
<div class="live-input" :class="cssClass">
<component :is="inputType" :state="currentState" :value="value" :errors="errors"
v-on="$listeners" v-bind="$attrs" class="d-inline-block"/>
</div>
</template>
props: {
as: { type: String, default: 'text' },
label: { type: String },
hint: { type: String },
inline: { type: Boolean, default: false },
},
data() {
return {
inputType: this.as || TextInput,
currentDirty: this.dirty,
selfUpdate: false,
}
}
Then I have a second component select select-input.vue
<template>
<b-select :value="value" @input="$emit('input', $event)"
ref="input" :state="state" :options="optionsForSelect"/>
</template>
props: {
options: { type: Array },
},
data() {
const sampleOption = this.options[0]
const valueMethod = tryProperties(sampleOption, ['value', 'id'])
const textMethod = tryProperties(sampleOption,
['text', 'name', 'label', 'toS']
)
return {
localOptions: this.options,
optionsForSelect: this.options.map(option => {
if (typeof option === 'string') {
return { value: option, text: option }
} else {
return {value: option[valueMethod], text: option[textMethod]}
}
}),
}
},
First this.books.length equals to zero, then I updated async and it has some entries, When I trace the availableBooks object seems that is been updated correctly but the select dropdown is not been updated.
Also seems that prop options has been updated but still the component is not been rerendered.
watch: {
options: function(newVal, oldVal) { // [{id: '2', text: 'test2'}]
console.log('Prop changed: ', newVal, ' | was: ', oldVal)
}
},
Upvotes: 0
Views: 2051
Reputation: 400
If you want to get updates for the options
prop in order to re-render your component when options
changes, you should use a computed
attribute for optionsForSelect
instead of a data
one. When using data
the value gets copied in the component and will only get re-rendered when the data
attribute is changed locally.
If you use a computed
property, when the parent component changes the prop options
value, the computed
attribute will get re-evaluated and your component will render again.
computed: {
optionsForSelect() {
if (typeof option === 'string') {
return { value: option, text: option }
} else {
return {value: option[valueMethod], text: option[textMethod]}
}
}
}
The computed
property would be my preferred approach.
However, you can also accomplish this with the data
attribute you have. You would have to add a watcher for the options
prop and assign the new value each time the prop is updated to optionsForSelect
data attribute.
watch: {
options: function(newVal, oldVal) {
// Update this.optionsForSelect value here
}
}
Hope it helps.
Upvotes: 2
Reputation: 386
Once that have entered the WATCH function, you can update the select-input view with this.$forceUpdate().
watch: {
options: function(newVal, oldVal) { // [{id: '2', text: 'test2'}]
// console.log('Prop changed: ', newVal, ' | was: ', oldVal)
this.$forceUpdate()
}
}
Upvotes: 1