returning this.user (a global computed property) works as expected. Of course, I’m making a copy because I do not want to overwrite the actual user data. So, I’m using Object.assign. However, once I include return Object.assign({}, this.user) (opposed to this.user), the watch method no longer functions.
Here is my template (I am using bootstrap-vue):
<template> <form role="form"> <b-form-group label="First Name" label-for="basicName" :label-cols="3" :horizontal="true"> <b-form-input id="user-name-first" type="text" v-model="userFormData.fname"></b-form-input> </b-form-group> <b-form-group label="Last Name" label-for="basicName" :label-cols="3" :horizontal="true"> <b-form-input id="user-name-lirst" type="text" v-model="userFormData.lname"></b-form-input> </b-form-group> <b-form-group label="Email" label-for="user-email" :label-cols="3" :horizontal="true"> <b-form-input id="user-email" type="text" v-model="userFormData.email"></b-form-input> </b-form-group> <b-form-group :label-cols="3" :horizontal="true"> <b-button type="submit" variant="primary">Save changes</b-button> <b-button type="button" variant="secondary" @click="userFormCancel">Cancel</b-button> </b-form-group> </form> </template>
So, this works and sets editsPending to true whenever changes are applied to userProfile (via v-model on an input)
<script> export default { name: 'userProfile', data () { return { editsPending: false } }, computed: { userFormData: function () { return this.user } }, watch: { userFormData: { deep: true, handler (val) { this.editsPending = true } } }, methods: { userFormCancel () { this.editsPending = false } } } </script>
…but this does not; userFormData becomes a clone of user but editsPending is not affected by updates to userFormData.
<script> export default { name: 'userProfile', data () { return { editsPending: false } }, computed: { userFormData: function () { return Object.assign({}, this.user) } }, watch: { userFormData: { deep: true, handler (val) { this.editsPending = true } } }, methods: { userFormCancel () { this.editsPending = false } } } </script>
Can anyone explain why this may be happening and suggest a viable solution?
Advertisement
Answer
A computed property will only re-evaluate when some of its dependencies have changed. (source)
That’s why it works with return this.user
and not with Object.assign
because it’s not a reactive dependency.
If you want reactive data you should initialize userFormData
as an empty object data and assign your user when your Vue instance is created:
data () { return { editsPending: false, userFormData: {} } }, created() { this.userFormData = Object.assign({}, this.user) },