1

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.

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

i think i had to use this.$set because the component doesn't know about the nested .roles property of user, so i have to explicitly set it that way. i'll try just doing this.user.roles.push and see if that possibly works though. otherwise i can try setting roles as an explicit property of the component, separate from user
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.