[Vuejs]-Undefined route.params when passing data between components via route.push

0👍

Because your goal is to send data after route to new page with the help of route.push, I ignored some part of your codes (like using table or v-for that you used in Homepage.vue). Here is my codes that I think could help you:

Homepage.vue:

<template>
  <div @click="onAboutClick(cveData.cve, cveData.packages)">
    some text
  </div>
</template>

<script>
export default {
  data() {
    return {
    cveData: { "cve": "CVE-2022-45869", "severity": "Medium", "packages": [ { "package": "kernel", "version": "5.15.80.1", "owner": "joslobo", "detection_date": "12-03-2022", "BranchStatus": { "1.0": { "sourceBranch": "NULL", "status": "NULL", "detectedOn": "NULL", "patchedOn": "NULL", "firstPatchedPackageRelease": "NULL", "fixReleaseDate": "NULL", "aid": "NULL", "qid": [ "NULL" ] }, "2.0": { "sourceBranch": "2.0", "status": "Unpatched", "detectedOn": "12-03-2022", "patchedOn": "NULL", "firstPatchedPackageRelease": "NULL", "fixReleaseDate": "NULL", "aid": "11574", "qid": [ "Not Assigned" ] } } }, { "package": "kernel", "version": "5.10.155.1", "owner": "joslobo", "detection_date": "12-03-2022", "BranchStatus": { "1.0": { "sourceBranch": "1.0", "status": "Unpatched", "detectedOn": "12-03-2022", "patchedOn": "NULL", "firstPatchedPackageRelease": "NULL", "fixReleaseDate": "NULL", "aid": "11573", "qid": [ "Not Assigned" ] }, "2.0": { "sourceBranch": "NULL", "status": "NULL", "detectedOn": "NULL", "patchedOn": "NULL", "firstPatchedPackageRelease": "NULL", "fixReleaseDate": "NULL", "aid": "NULL", "qid": [ "NULL" ] } } } ] }
    }
  },
  methods: {
    onAboutClick: function (cve_id, cve_obj) {
      console.log('----> cve_id = ', cve_id)
      console.log('----> cve_obj = ', cve_obj) // cve_obj is successfully printed at this point
      let objData = JSON.stringify(cve_obj);
      this.$router.push(
          {
            name: 'clickthru',
            query: {'cve_id': cve_id},
            params: {'cve_obj': objData}
          }
      )
    } // end of function
  }
}
</script>

clickthru.vue:

<template>
  <div>
    this is "clickthru" compo
  </div>
  <section>
    {{ cve_id }}
  </section>
  <section v-for="item in cve_obj">
    <div v-for="subItem in item">
      {{ subItem }}
    </div>
  </section>
</template>

<script>
export default {
  name: "clickthru",

  beforeRouteEnter (to, from, next) {
    next(vm => {
      console.log(from);
      if (from.name == "about") {
        /* you must enter the name of your home component instead of "about", I used about page so I entered "about". You can find necessary info by seeing "console.log(from)" in your console. */
        vm.cve_obj = JSON.parse(vm.$route.params.cve_obj);
        /* We set the data to "localStorage" to retrieve it when the page refreshed on mounted hook. */
        localStorage.setItem("cveDataStore" , vm.$route.params.cve_obj);
      }
    })
  },


  data() {
    return {
      cve_id: this.$route.query.cve_id,
      cve_obj: JSON.parse('[{"message": "wrong info"}]')
    };
  },

  mounted() {
    if (this.cve_obj !== JSON.parse('[{"message": "wrong info"}]')) {
      if (localStorage.getItem("cveDataStore")) {
        this.cve_obj = JSON.parse(localStorage.getItem("cveDataStore"));
      }
    }
  }
}
</script>

I used "beforeRouteEnter" hook in the clickthru.vue component because according to this GitHub page passing params directly may cause some errors or warnings when page is reloading. So we could store data in localStorage to show it to the user after reloading the page.

According to vue-router docs:

When specifying params, make sure to either provide a string or number (or an array of these for repeatable params). Any other type (like undefined, false, etc) will be automatically stringified.

Because your cve_obj data is of type "object", to ensure that no problem will happen, I used JSON.stringify in Homepage.vue to convert it to a string. Then in the clickthru.vue component, I convert it back to an object with the help of computed properties and JSON.parse method.

If you use this code, you won’t need to use props: true in the main.js, because you don’t use props at all.

0👍

As I mentioned in the comments, passing objects as query params is not an appreciated way, so there are two ways to do this-

Approach 1-
Pass only cve_id to the new route and when the new route’s page is mounted, fetch the cve_object from the backend using this query param cve_id.
This approach is useful and recommended because you will always have updated data from the backend.

If you follow this approach then a few changes are necessary-

  1. In Homepage.vue pass only cve_id to your new route-
methods: {
    onAboutClick(cve_id) {
        this.$router.push({
            name: "clickthru",
            query: { cve_id: cve_id },
        });
    },
},
  1. On clickthru.vue mounted hook, init the API call to get cve_data of that id-
mounted() {
 // Make an API call to fetch the respected id's data
}

Approach 2-
When you receive the records (on which you are looping) in your HomePage.vue, save this data to your Vuex state. Now, same as approach one, pass only the cve_id to your new route and when the new route’s page is mounted, fetch the respected data from the Vuex state instead of fetching from an extra API call.

If you follow this approach then the process will be like this-

  1. When you get the backend response in your HomePage.vue, dump it in the state, like this-
const store = new Vuex.Store({
  state: {
    records: []
  },
  mutations: {
    SET_RECORDS (state, backend_response) {
      // mutate state
      state.records = backend_response;
    }
  }
})
  1. Same as approach one, you have the cve_id in your route query, so use it to fetch the respected cve_object from the state. So, on clickthru.vue mounted, do this-
<script>
export default {
    data() {
        return {
            cve_object: null,
        };
    },
    mounted() {
        this.cve_object = this.$store.state.records.find(
            (item) => item.id == this.$route.query.cve_id,
        );
    },
};
</script>

In this way you will have your records in the state, so you can find any single record using the query cve_id on any page.

NOTE-
I only give the idea to fetch and set data from the state. If you want to follow the second approach, just read about Vuex and follow the documentation.
You can also check out this here complete guide on how to set up Vuex in the Vue application.

Leave a comment