Why Vue Component Won't Update On Select Change
Why Vue Component Won't Update On Select Change
I have a form that changes some text within a vue component when a select box is changed. I've created a highly minimized version of this in jsfiddle to show the issue I'm experiencing:
https://jsfiddle.net/ywaug7ft/
HTML:
<div id="app">
<h5>Select a gender</h5>
<select v-model="gender">
<option disabled="disabled" value>Select...</option>
<option value="1">Male</option>
<option value="2">Female</option>
<option value="3">Couple</option>
</select>
<div></div>
<detail-component v-for="(detail, index) in details" :data="detail" :index="index"></detail-component>
details
</div>
<template id="details">
<div>
<h4><span v-if="item.gender == 3 && index == 0">Her</span><span
v-else-if="item.gender == 3 && index == 1">His</span><span v-else>Your</span> Health Details</h4>
<div>Index: index</div>
<div>Gender: item.gender</div>
</div>
</template>
Vue:
Vue.component('detail-component',
template: '#details',
props: ['data', 'index'],
data()
return
item:
gender: this.data.gender
);
var app = new Vue(
el: '#app',
data:
gender: '',
details: ,
options:
gender:
"1": "Single Female",
"2": "Single Male",
"3": "Couple"
,
watch:
gender: function(val)
this.details = ;
if (val == 1)
this.details.push(gender: 1);
else if (val == 2)
this.details.push(gender: 2);
else if (val == 3)
this.details.push(gender: 3, gender: 3);
);
Basically, when I select female
or male
from the dropdown, my vue component should update the h tag to say Your Details
. When I select couple
, my view component should update to say Her Details
and His Details
. However, it's not updating the first index to Her
but instead maintains Your
.
female
male
Your Details
couple
Her Details
His Details
Her
Your
Take a look at the jsfiddle and you'll see what I mean exactly.
Just trying to understand what I'm doing wrong. I thought that using watcher would be reactive in the component.
3 Answers
3
You are using the wrong reference: your detail-component
receives data
but your reference item
in your template.
detail-component
data
item
If you change the template as follows:
<template id="details">
<div>
<h4>
<span v-if="data.gender === 3 && index === 0">Her</span>
<span v-else-if="data.gender === 3 && index === 1">His</span>
<span v-else>Your</span>
Health Details
</h4>
<div>Index: index</div>
<div>Gender: data.gender</div>
</div>
</template>
it will work (see this Fiddle).
The problem here was that you somehow had gender 1 in the first detail object and therefore got "Your" instead of "Her".
You are not watching inside the child if a prop value is getting updated.
So here whenever the prop data
changes you need to watch
it as well in the child component.
data
watch
Watch Fiddle,
watch:
data(val)
this.item.gender=val.gender
Or computed property Fiddle.
computed:
item()
return this.data;
Updated. I prefer watcher for single value updates.
– Helping hand
Aug 23 at 19:56
The problem is caused by this part of your code:
data()
return
item:
gender: this.data.gender
When you assigned the value of the gender
property from your prop into a property inside your data()
object, it loses reference immediately. So when the data
prop was updated, it didn't update your item.gender
.
gender
data()
data
item.gender
If your purpose is just to alias
the gender into a variable with shorter name for ease of use, you can use computed
properties which will also update every time the data
is changed.
alias
computed
data
computed:
item()
return this.data
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
I usually like using computed properties rather than watching, I think it's cleaner. That way you don't have to both define the calculation logic, and a magic place to store the result.
– gnud
Aug 23 at 19:32