Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Splicing array does not re-render table row Vuejs

I have a user table generated with data from an ajax request. Table roughly looks like this: [Image of Table][1]

When an admin edits a user's username, I want the user's row to re-render with the changes (specifically the users firstname and lastname).

I create the table fine. The models work fine. My parent component receives the edited data just fine in my edit() method, but I can't seem to make my target row re-rendered with my changed data. How can I make my target row update?

I tried the following and it didn't work:

  • How to update a particular row of a vueJs array list?
  • https://v2.vuejs.org/v2/guide/list.html#Caveats
  • I have set key to my row
  • Tried setting my listOfUsers with Vue.set()
  • Tried using Vue.set() in place of splice

Here is my parent vue component with the following (I took out irrelevant details):

TEMPLATE:

<table>
    <thead>
        <tr>
            <th>Name</th>
            <th>Email Address</th>
            <th>Created</th>
            <th>Stat</th>
            <th>Actions</th>
        </tr>
    </thead>
    <tbody>
        <tr v-for="(user, index) in listOfUsers" :key="'row' + user._id"> 
            <td>{{user.first_name + ' ' + user.last_name}}</td>
            <td>{{user.email}}</td>
            <td>{{user.created}}</td>
            <td>
                <a v-if="user.confirmed" @click="determineButtonClicked(index, 'confirm')"></a>
                <a v-else @click="determineButtonClicked(index, 'unconfirm')"></a>
            </td>
            <td class="buttonCase">
                <a @click="determineButtonClicked(index, 'info')"></a>

                <a v-if="user.blocked" @click="determineButtonClicked(index, 'blocked')"></a>
                <a v-else @click="determineButtonClicked(index, 'block')"></a>
        
                <a v-if="user.enforce_info === 'required'" @click="determineButtonClicked(index, 'enforceInfoActive')"></a> 
                <a v-else-if="user.enforce_info === 'done'" @click="determineButtonClicked(index, 'enforceInfoChecked')"></a>
                <a v-else @click="determineButtonClicked(index, 'enforceInfo')"></a>

                <modal v-if="usersList[index]" @toggleClickedState="setState(index)" @editUser="edit(index, $event)" :id="user._id" :action="action"></modal>
            </td>
        </tr>
    </tbody>
</table>

SCRIPT

<script>
    export default {
        created: function() {
            let self = this;
            $.getJSON("/ListOfUsers",
            function(data){
                self.listOfUsers = data;
            });
        },
        data: function() {
            return {
                listOfUsers: [],
            }
        },
        methods: {
            edit(index, update){
                let user = this.listOfUsers[index];
                user.firstName = update.firstName;
                user.lastName = update.lastName;
                
                // this.listOfUsers.splice(index, 1, user)
                this.listOfUsers.$set(index, user)
            }
        }
    }
</script>

Thank you for your time and help! [1]: https://i.sstatic.net/lYQ2A.png

like image 625
Leesa Avatar asked Dec 30 '25 23:12

Leesa


1 Answers

Vue is not updating in your edit method because the object itself is not being replaced. Properties of the object do change, but Vue is only looking for the object reference to change.

To force the array to detect a change in the actual object reference, you want to replace the object, not modify it. I don't know exactly how you'd want to go about doing it, but this hacked together fiddle should demonstrate the problem so you can work around it: http://jsfiddle.net/tga50ry7/5/

In short, if you update your edit method to look like this, you should see the re-render happening in the template:

methods: {
   edit(index, update){
      let currentUser = this.listOfUsers[index];
      let newUser = {
         first_name: update.firstName,
         last_name: update.lastName,
         email: currentUser.email,
         created: currentUser.created
      }

      this.listOfUsers.splice(index, 1, newUser)
   }
}
like image 148
Adam Avatar answered Jan 01 '26 15:01

Adam



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!