Comforse
Comforse

Reputation: 2066

VueJS: observer object instead of Array

I have this small one page VueJS app which uses Firebase. The problem I am currently facing is when I try to retrieve a collection from Firebase in a component. Instead of returning an array, the vue instance returns an observer object, more precisely [__ob__: Observer]. I understand that Vue JS uses this object to do its magic, what I don't understand is what am I supposed to do to get the actual array. I cannot do anything with that object, can't iterate it. I tried any lifecycle method to try and do it, but no luck. What is weirder is that when I close and open again the Chrome console (F12), the methods get called again and the object is actually resolved into the array. I initially thought that the data may not be retrieved yet, but the data is present in the object itself, I just can't access it.

Here's my code:

Vue instance:

new Vue({
  el: '#app',
  firebase: {
    orders: firebase.database.ref('orders').orderByChild('created_at'),
    members: firebase.database.ref('members').orderByChild('created_at')
  },
  router,
  template: '<App/>',
  components: { App }
})

Component code:

export default {
  data () {
    return {
      'member': null
    }
  },
  computed: {
    isMemberLoaded: function () {
      this.member !== null
    }
  },
  mounted: function () {
    console.log('mounted')
    this.init()
    console.log(this.$root.members) // [__ob__: Observer]
  },
  created: function () {
    console.log('created')
    console.log(this.$root.members) // [__ob__: Observer]
  },
  updated: function () {
    console.log('updated')
    console.log(this.$root.members) // [__ob__: Observer]
  },
  methods: {
    init: function () {
      console.log('init')
      console.log(this.$root.members) // [__ob__: Observer]
    }
  }
}

The observer object looks like this:

[__ob__: Observer]
    0:
      .key:(...)
      code:(...)
      created_at:(...)
      email:(...)
      name:(...)
      __ob__:Observer {value: {…}, dep: Dep, vmCount: 0}
      get .key: ƒ reactiveGetter()
      set .key: ƒ reactiveSetter(newVal)
      get code: ƒ reactiveGetter()
      set code: ƒ reactiveSetter(newVal)
      get created_at: ƒ reactiveGetter()
      set created_at: ƒ reactiveSetter(newVal)
      get email: ƒ reactiveGetter()
      set email: ƒ reactiveSetter(newVal)
      get name: ƒ reactiveGetter()
      set name: ƒ reactiveSetter(newVal)
      __proto__: Object
      length: 1
    __ob__: Observer {value: Array(1), dep: Dep, vmCount: 0}
    __proto__: Array

What am I missing here?

Upvotes: 8

Views: 18909

Answers (3)

guillim
guillim

Reputation: 1577

Simply do:

var parsedObj = JSON.parse(JSON.stringify(this.$root.members))
console.log(parsedObj)

It will convert the [ob: Observer] to its value

Upvotes: 5

Comforse
Comforse

Reputation: 2066

So, with the help of @Georgi Antonov I managed to solve my issue in this way:

I changed my component like this:

methods: {
    init: function () {
      let _vm = this
      let _id = _vm.$route.params.id
      _vm.$root.$firebaseRefs.members.child(_id).on('value', function (d) {
        console.log(d.val())
      })
    }
  }

The essential parts is _vm.$root.$firebaseRefs.members. This actually resolves in a firebase object (collection?) and from there you can access the data. The child function just retrieves the element with the passed id. It's not an array, but I don't require one as I don't need to search. In order to get the entire list just change to _vm.$root.$firebaseRefs.members.on('value', function() {}.

While Georgi Antonov provided the answer above, that is not quite correct. The firebase references are defined in the Vue instance and you don't need to declare them again in the component. Hence, this would not have the firebase refs in the scope.

Upvotes: 0

Georgi Antonov
Georgi Antonov

Reputation: 1641

I don't know how this firebase thing works. but im sure you can access the $firebase object with this in each component because it is obviously global and find your data there.

export default {
      data () {
        return {
          'member': null
        }
      },
      firebase: {
         members: db.ref('members')
       },
      computed: {
        isMemberLoaded: function () {
          this.member !== null
        }
      },
      mounted: function () {
        console.log('mounted')
        this.init()
        console.log(this.$root.members) // [__ob__: Observer]
      },
      created: function () {
        console.log('created')
        console.log(this.$root.members) // [__ob__: Observer]
      },
      updated: function () {
        console.log('updated')
        console.log(this.$root.members) // [__ob__: Observer]
      },
      methods: {
        init: function () {
          console.log('init')
          console.log(this.$root.members) // [__ob__: Observer]
        }
      }
    }

Upvotes: 0

Related Questions