8

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?

9
  • is the observer object empty ? Commented Sep 14, 2017 at 11:32
  • @GeorgiAntonov, no, the data is in there. Commented Sep 14, 2017 at 11:33
  • so what is the problem ? access the array which is in the observer object Commented Sep 14, 2017 at 11:34
  • @GeorgiAntonov can't, check my post again to see how the object looks Commented Sep 14, 2017 at 11:37
  • instead of using this.$root use this.$firebaseRefs Commented Sep 14, 2017 at 11:44

3 Answers 3

5

Simply do:

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

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

Sign up to request clarification or add additional context in comments.

1 Comment

Sure, but even better, I will let Evan You (creator of VueJS) answer : here
0

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]
        }
      }
    }

Comments

0

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.

Comments

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.