Reputation: 937
So I have the following code that either assigns or removes an existing 'role' to a user:
onAddRole(role) {
let roles = this.user.roles
roles.push(role)
this.$set(this.user, roles)
console.log(this.user.roles)
this.success.role_update = true
},
onRoleDelete(selected_role) {
let i = this.user.roles.map(role => role.id).indexOf(selected_role.id)
if (i !== -1) {
let roles = this.user.roles
roles.splice(i, 1)
this.$set(this.user, roles)
console.log(this.user.roles)
this.success.role_update = true
}
}
Here is my data property for the component:
data: function() {
return {
user: null,
success: {
permission: null,
invalidation: null,
fetch: null,
save: null,
role_update: null
},
loading: false
}
},
And here is a snippet of the relevant html:
<b-row>
<b-col md="6">
<b-row v-if="user">
<b-col md="12">
<user-roles
:user="user"
@add_role="onAddRole"
@set_role="onRoleSet"
@role_failure="roleFail"
@role_delete="onRoleDelete"
/>
</b-col>
</b-row>
<loading v-if="loading" />
</b-col>
</b-row>
Basically this code works fine if I add a role once or twice. However, after the third time I remove or add a user role, Vue stops re-rendering the component. Any ideas why this would happen?
The console.logs show that the property itself is updated correctly, but the view does not update.
Upvotes: 1
Views: 142
Reputation: 937
So the solution to having it work consistently was to separate the roles property from users, like so:
data: function() {
return {
user: null,
roles: null,
success: {
permission: null,
invalidation: null,
fetch: null,
save: null,
role_update: null
},
loading: false
}
},
then just update the roles property for the event handler methods like you normally would. no need to use .$set
:
onRoleSet({ role, i }) {
this.roles.splice(i, 1, role)
this.success.role_update = true
},
onAddRole(role) {
this.roles.push(role)
this.success.role_update = true
},
onRoleDelete(selected_role) {
let i = this.roles.map(role => role.id).indexOf(selected_role.id)
if (i !== -1) {
this.roles.splice(i, 1)
this.success.role_update = true
}
}
so far this is working consistently for me and the component updates like it's supposed to.
It seems that having a nested property in the component's data
object seems to cause me a lot of problems with Vue, so it's best to avoid doing that
Upvotes: 0
Reputation: 9362
This may not be the final resolution but I see two issues that may be the root cause.
Whenever you do:
let roles = this.user.roles
you're creating a reference to that array so when you next do:
roles.push(role)
You're actually just essentially doing
this.user.roles.push(role)
So really there's not much of a reason to even allocate the let roles
variable.
Secondly, this.$set
needs the name of the property. So it should be
this.$set(this.user, 'roles', roles)
or you'll be creating an undefined property on the user with roles
assigned to it.
I'm not quite sure why you're using this.$set
though since your already modifying the roles when you push()
and it would just be assigning the same array back to the property the way you're currently doing it.
Upvotes: 1