Home > Software design >  VueJS array not updating
VueJS array not updating

Time:01-25

Here is the code

<template>

 <div id="left_container" ref="usersContainer">
  <button v-for="user in users" :key="user.userID" >{{ user.username }}</button>

</div>
<div id="right_container">
    <ul id="messages"></ul>
    
    <div id="bottom_container">
    
    <label id="lt"></label>
    <form id="form" @submit.prevent="onSubmit" action="">
    <input id="input" v-model="in_msg" autocomplete="off" v-on:input="vChanged"/><button>Send</button>
    </form>
  
</div>
</div>

</template>
  
  <script>
  import socket from "../socket"
 
  
  export default {
    name: "MyChat",
    components: {
     
    },
    data() {
      
      return {
        in_msg:'',
        users: [],
        selectedUser: null,
      };
    },
    methods: {
      onSubmit()
      {
        console.log(this.users);
        if(this.selectedUser)
        {
          var content = this.in_msg;
          socket.emit("private message", {
            content,
            to: this.selectedUser.userID,
          });
    
        }
        else{
        if (this.in_msg) {
          socket.emit('chat message', this.in_msg);
          this.in_msg = '';
        }
       }
      },
      vChanged()
      {
        socket.emit('on_c');
      },

      
    },
    created()
    {
      
      var messages = document.getElementById('messages');
      var lbl_writing = document.getElementById('lt');
      
      socket.on('chat mess', function(msg) {
        
        var item = document.createElement('li');
        item.textContent = msg;
        messages.appendChild(item);
        window.scrollTo(0, document.body.scrollHeight);
      });
      socket.on("private message", ({ content, from }) => {
        var msg = from   " : "   content;
        var item = document.createElement('li');
        item.textContent = msg;
        messages.appendChild(item);
        window.scrollTo(0, document.body.scrollHeight);
  
});
      socket.on('chat message not', function(msg) {
       lbl_writing.textContent = msg;
      });
      socket.on('users',function(users)
      {
       
        this.users = [...users];
        console.log(this.users);
        //const dlv = document.getElementById('left_container');
        //dlv.innerHTML = '';
      //   this.users.forEach(user => {
      //   const button = document.createElement('button');
      //   button.innerHTML = user.username;
        
      //   //button.addEventListener('click',this.onClick(user));
       
      //   //dlv.appendChild(button);
      // });
      });
      socket.on('user connected',function(user)
      {
       
        this.users.push(user);
        // const dlv = document.getElementById('left_container');
        // //dlv.innerHTML = '';
       
        // const button = document.createElement('button');
        // button.innerHTML = user.username;
        
        // //button.addEventListener('click',this.onClick(user));
       
        // dlv.appendChild(button);
    
      })
    }
   
  };
  </script>
    <style scoped>
 
    #left_container {width: 19vw;position: absolute;top: 0;bottom:0; background-color: white;border: dashed black;display: flex;flex-direction: column;}
    #right_container {width: 80vw;display: flex; background-color:white;flex-direction: column;position: absolute;margin-left: 19.5vw;top:0;bottom: 0;}
    #bottom_container { display: flex; position: absolute; bottom: 0;left: 0;right: 0; flex-direction: column;}
    #form { background: rgba(0, 0, 0, 0.15); padding: 0.25rem; display: flex; height: 3rem; box-sizing: border-box; backdrop-filter: blur(10px); }
    #input { border: none; padding: 0 1rem; flex-grow: 1; border-radius: 2rem; margin: 0.25rem; }
    #input:focus { outline: none; }
    #form > button { background: #333; border: none; padding: 0 1rem; margin: 0.25rem; border-radius: 3px; outline: none; color: #fff; }
    #pv { background-color: red;color: #fff;}
    #lt { background: rgba(0, 0, 0, 0.15); padding: 0.25rem; display: flex; height: 3rem; box-sizing: border-box; backdrop-filter: blur(10px); }
    #lo { background: rgba(0, 0, 0, 0.15); padding: 0.25rem;  display: flex; height: 3rem; box-sizing: border-box; backdrop-filter: blur(10px); }


    #messages { list-style-type: none; margin: 0; padding: 0; }
    #messages > li { padding: 0.5rem 1rem; }
    #messages > li:nth-child(odd) { background: #efefef; }
    .user-button {
  background-color: blue;
  color: white;
}

  </style>
  

In the template part the v-for on buttons isn't displaying anything because I'm unable to update data() -> users array. We can see in the socket.on('users') function the array is supposed to be updated but the users array isn't updated after the function is finished. It comes back to empty array after the ending bracket of socket.on('users'...)

CodePudding user response:

Vue allows for the page elements to react to variable changes rather than explicitly modifying the DOM with getElementById / createElement / appendChild.

Similar to how you are managing the display of users, use Vue data for an array of messages and a string for the label text.

<template>
  <div id="left_container" ref="usersContainer">
    <button v-for="user in users" :key="user.userID" >{{ user.username }}</button>
  </div>
  <div id="right_container">
    <ul id="messages">
      <!-- using the array index as a key is not recommended, but 
           will work for simple array appending -->
      <li v-for="(message, index) of messages" :key="index">
        {{ message.msg }}
      </li>
    </ul>
    <div id="bottom_container">
    <label id="lt">
      {{ lbl_writing }}
    </label>
    <form id="form" @submit.prevent="onSubmit" action="">
      <input id="input" v-model="in_msg" autocomplete="off" v-on:input="vChanged"/><button>Send</button>
    </form>
  </div>
  </div>
</template>

Then the script just needs to modify the messages and lbl_writing variables, rather than modifying the elements directly

<script>
  import socket from "../socket"
 
  export default {
    name: "MyChat",
    data() {
      return {
        in_msg:'',
        users: [],
        selectedUser: null,
        messages: [],
        lbl_writing: null,
      };
    },
    mounted()
    {
      socket.on('chat mess', function(msg) {
        this.messages.push({ msg })
      });
      socket.on("private message", ({ content, from }) => {
        var msg = from   " : "   content;
        this.messages.push({ content, from, msg })
      });
      socket.on('chat message not', function(msg) {
        this.lbl_writing = msg
      });
      socket.on('users',function(users){
        this.users = [...users];
        console.log(this.users);
      });
      socket.on('user connected',function(user)
      {
        this.users.push(user);
      })
    }
   
  };
</script>

  • Related