Reputation: 5908
I have a table row, each containing a select. I wish that when the select option is changed, the data of the parent (containing the table) is updated.
<tbody>
<tr is="itemComponent"
v-for="(item, index) in items"
v-bind:index="index"
v-bind:item="item"
v-bind:item-attribute.sync="item.attribute"
</tr>
</tbody>
Then in itemComponent (receives item-attribute as props):
<td>
<select
v-bind:value="item-attribute"
v-on:change="$emit('update:item-attribute', $event.target.value)
>
<option v-bind:value="true">Yes</option>
<option v-bind:value="false">No</option>
</select>
</td>
Using Vue's Chrome extension, I can see that the <select>
is reactive to item.attribute
(if I change it manually, the selected option in the select changes), and that it also fires the 'update:item-attribute' event when changed, but it does NOT update the parent's item.item-attribute
value.
Since .sync is just sugar for v-on:update:item-attribute
, I would need to write something like this on the parent component if I didn't want to use .sync:
<tbody>
<tr is="itemComponent"
v-for="(item, index) in items"
v-bind:index="index"
v-bind:item="item"
v-bind:item-attribute="item.attribute"
v-on:update:item-attribute="updateItemAttribute"
</tr>
</tbody>
methods: {
updateItemAttribute: function(index,attributeValue) {
this.items[index].attribute = attributeValue;
}
}
And, on the child component, change the emit call in the select to (considering index is :
v-on:change="$emit('update:item-attribute', index, $event.target.value)
Shouldn't .sync help me on this and avoid having to write all this code? I couldn't find any mention of it working with v-for.
Upvotes: 2
Views: 2766
Reputation: 5908
The answer is that the event name should be camelCase, not kebab-case, at least for now.
The "at least for now" is because this is definitely confusing since Vue's documentation explicitly says to "always use kebab-case
as event names" (see here), but unfortunately you must use camelCase
when using the update:eventName
with the .sync
modifier.
Vue's developers are aware of this inconsistency and there's an open issue to either change the code behavior or rewrite the docs in this point. It also doesn't help that, as of now, the examples in the .sync
modifier use event names with single words. See https://github.com/vuejs/vuejs.org/issues/1648 for updates.
So, for now, when using .sync modifier, you should use $emit('update:propNameInCamelCase
)`.
Do not use $emit('update:prop-name-in-kebab-case
)` otherwise it won't work.
Thanks to @Jacob Goh for opening the github issue.
Upvotes: 3