I have select displayed in v-for
loop:
<div v-for="(n, key) in selectedLanguages">
<select class="input input__col"
v-model="currentLang[key]"
@change="changeLanguage(currentLang[key], key)"
id="lang_select">
<option value="pl">Polski</option>
<option value="en">Angielski</option>
<option value="es">Hiszpański</option>
</select>
</div>
To each select I'm adding changeLanguage method which is:
<script>
export default {
data() {
return {
currentLang: []
}
},
methods: {
changeLanguage(value, key) {
let data = { value, key };
this.$nuxt.$emit('change::language', data);
}
},
props: ['selectedLanguages']
}
</script>
and it is in child component. In parent I'm listening for this change::language
event:
this.$nuxt.$on('change::language', res => {
console.log(res);
this.selectedLanguages[res.key] = res.value;
console.log(this.selectedLanguages);
Although it's working correctly and it's updating selectedLanguages
array just fine it doesn't rerender interpolation {{ selectedLanguages }}
in parent. However it's correctly rerendering interpolation {{ selectedLanguages }}
in child where it's passed by props. Why?
It seems like vue doesn't "catch" that selectedLanguages
array have been changed. It only see when I .push
or .pop
this array. Is there something like apply
method in vue?
I found this link in documentation: https://v2.vuejs.org/v2/guide/list.html#Caveats and added this.$set(this.selectedLanguages, res.value, res.key);
in parent below my assignment but it didn't fix.
I found solution in Vue docs:
Due to limitations in JavaScript, Vue cannot detect the following changes to an array: When you directly set an item with the index, e.g. vm.items[indexOfItem] = newValue
I was doing exacly like above.
The solution is instead
this.selectedLanguages[res.key] = res.value;
use
this.$set(this.selectedLanguages, res.key, res.value);
which is basically a bit weird but it works.