Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue: empty array automatically populated with Observer object

I'm trying to init an empty array in the data and then get a JSON from the server and populate it.

The problem is that the array always have an extra Observer object so when i log it i see this:

empty items array: [ob: Observer]

here is a code excerpt:

data() {
        return {
            items: []
        }
    },
 created() {
         this.$http.get('/api/menus').then(function (response) {

            console.log('items before', this.items); //THIS LOGS items before: [__ob__: Observer]
             this.items = [].concat(response.body);
            this.items.forEach(function (item) {
              console.log('item', item);

              item.$add('active', false);

              item.tests.forEach(function (test) {
                  test.$add('active', false);
              });
        });

         }).catch(function (err) {
             console.error('err', err);

         });

     },

The problem is that when trying to add a new property to the objects in the array i get an error:

err TypeError: item.$add is not a function

when i debug i see it happens because it considers the observer object as part of the array.

Is it normal? should i just check if $add exists? what about when rendering it in the view, does Vue ignore this object?

like image 561
Tomer Avatar asked Oct 15 '25 18:10

Tomer


1 Answers

According to your code, you want to set active property in your items object to false. Also you want to set all the properties active in every item's tests property to false.

Vue.js is reactive and detect changes automatically, but only for objects themselves, not their properties. For array vue will only detect changes by those methods (more about list rendering in vue.js https://v2.vuejs.org/v2/guide/list.html#ad):

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

But how about properties? You can force vue to see change in deep of array or object with Vue.set(object, property, value) or this.$set in any Vue instance.

So, in your example you can implement it like this:

this.items.forEach(function (item, key) {
    console.log('item', item);

    this.$set(this.items[key], 'active', false);

    item.tests.forEach(function (test, testKey) {
        this.$set(this.items[key].tests[testKey], 'active', false);
    }, this);
}, this);

And it should work. Here is working example: http://jsbin.com/cegafiqeyi/edit?html,js,output (some ES6 features used, don't be confused)

like image 159
GONG Avatar answered Oct 18 '25 07:10

GONG



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!