0

I have an array in JS/Vue that I would like to display in <ul>/<li> tags, and keep updated as the array gets new elements.

HTML:

<ul id="ulist">
    <li v-for="user in users">
        @{{ user }} <!-- "@" needed since this is in a laravel project with blade templates -->
    </li>
</ul>

JS:

<script>
  var socket = io('localhost:3000');

  new Vue({
     el: "#ulist",

     data: {
            users: []
           },

     mounted: function() {
        this.$nextTick(function() {
           socket.on('test-action', function(data) {
              this.users.push(data.username);
              console.log(data.username);
           }.bind(this));
        });
     }
  });
</script>

The array is being properly populated (as I can see via the console.log statement), but the <li v-for="user in users">... part doesn't seem to be working as none of the <li>...</li> elements get created. What am I doing wrong here?

Just to clarify: if I add hard coded values to the users array, those values show up in <li> elements fine, but no additional values that are added to the array (in the mounted function) show up in <li>...</li> elements.

Edit: version is 2.5.13, if it matters

1

2 Answers 2

2

Can you try this ?

<script>
    var socket = io('localhost:3000');

    new Vue({
        el: "#ulist",

        data: {
            users: []
        },

        mounted: function() {
            var _self = this;
            this.$nextTick(function() {
                socket.on('test-action', function(data) {
                    self.users.push(data.username);
                    console.log(data.username);
                }.bind(this));
            });
        }
    });
 </script>
Sign up to request clarification or add additional context in comments.

2 Comments

is _self and self are same ?
Thanks for the answer. But it doesn't seem to make a difference for me. I always thought using _self = this; was an alternative (in some situations) to .bind(this). Is that right? I didn't think both would be needed like you have in your example
2

The problem is with the scope of your this variable. In your code this line:

this.users.push(data.username); 

is scoped to the function call within the ajax request, if you use () => it will keep the current scope in context within your method. Also, you shouldn't need nextTick within the mounted call so try this:

<script>
    var socket = io('localhost:3000');

    new Vue({
        el: "#ulist",

        data: {
            users: []
        },

        mounted: function() {
            socket.on('test-action', data => {
                this.users.push(data.username);
                console.log(data.username);
            });
        }
    });
 </script>

Although you were using bind(this) you were using this within nextTick which was causing scope issues.

Another thing worth noting, lists require a key in vue v?? (I can't remember which) so it's best to add a key when using v-for:

<ul id="ulist">
    <li v-for="(user, index) in users" :key="index">
        @{{ user }} <!-- "@" needed since this is in a laravel project with blade templates -->
    </li>
</ul>

2 Comments

Thanks for your answer. Using the arrow function syntax I don't think I can use .bind(this) anymore. Is that correct? I tried using this example but it results in a syntax error unless the bind call is removed.
Apologies, that was a mistake on my part. Just remove the bind and it should all work out well. I've updated my code to suit.

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.