Search code examples
javascriptfirebasevue.jsfirebase-realtime-databasevuefire

Get firebase data (with or without vuefire) using a parameter from router before DOM renders in Vuejs?


I am navigating into a view from another view and passing the itemdId as param value to vue router.

I want to be able to call firebase with that itemId so that I can filter the data and the filtered result/data is used in the UI. I am using vuefire.

What is happening is that vue starts rendering before the data is available in created() and I see error is the console saying view is referring to undefined property values.

Is there a way to render the view after the data is available?

I have tried the using beforeMount as well as created and beforeCreate approaches.

See code below:

<h1>{{projects[0].project_name}}</h1> //it says type error. cannot read property project_name of undefined. Sometimes on refresh it works but most times it does not. 

Script code below:

    let projectsRef = db.ref('projects');
    export default {
        name: 'ProjectDetailsOpenInvesting',
        props: {
          data: Object
    },
    firebase:{
      projects: projectsRef
    },
    data(){
      return {
        projects:[],
        .....

      }
    },
    created(){
      var that = this;
      console.log(this.$route.params.itemid) //this works
      this.projects = this.projects.filter(function(p){
        return p.project_id == that.$route.params.itemid //this works as well
      })
    }

Firebase screenshot here


Solution

  • As you have mentioned, one approach is to fetch after navigation, i.e. fetch the data in the component's created hook.

    To do that with vuefire you need to programatically bind the Realtime Database projectsRef Reference to the projects property in your Vue application, as follows:

    created(){
      console.log(this.$route.params.itemid)
      const itemId = this.$route.params.itemid;
      this.$rtdbBind('projects', projectsRef.orderByKey().equalTo(itemId)).then(projects => {
         this.projects === projects;
      });
    }
    

    As explained in the API doc:

    $rtdbBind returns a Promise that is resolved once the data has been retrieved and synced into the state.

    Note that you need to install the rtdbPlugin plugin: https://vuefire.vuejs.org/api/vuefire.html#rtdbplugin


    Also note that instead of filtering the desired project item in the front-end (with filter(function(p){return p.project_id == that.$route.params.itemid}))), we filter it in the back-end, at the level of the database (projectsRef.orderByKey().equalTo(itemId)) which is more efficient and which avoids transmitting the entire set of objects from the back-end to the front-end (and avoids paying for this downloaded volume, see https://firebase.google.com/pricing?authuser=0).