Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Rod2rick's avatar

VueJs Pass data from one component to another and fetch data

Hi im looking for a way to pass data from my product list page to my product detail page and fetch all the json data.

Here is my code Product List Page

<template>
	<router-link :to="{ name: 'projects-detail', params: { id: project.id, project: project }}">
		<div>
			<img
				:src="project.img"
				:alt="project.name"
				class="rounded-t-xl border-none"
			/>
		</div>
		<div class="text-center px-4 py-6">
			<p
				class="font-general-semibold text-xl text-ternary-dark dark:text-ternary-light font-semibold mb-2"
			>
				{{ project.title }}
			</p>
			<span class="font-general-medium text-lg text-ternary-dark dark:text-ternary-light">
				<i class="text-indigo-600 dark:text-indigo-300 lni lni-map-marker mr-2"></i>
				{{ project.location }}
			</span>
			<p
				class="mt-4 font-general-semibold text-base text-ternary-dark dark:text-ternary-light font-semibold mb-2"
			>
				{{ Number (project.price).toLocaleString() }} {{currency}} / {{ project.period }}
			</p>
		</div>
	</router-link>
</template>

<script>

export default {
  data () {
    return {
      currency: 'FCFA',
    }
  },
	props: ['project'],
};
</script>

Here is my code Product Detail Page

<template>
    <div class="container" style="padding: 6rem 0px;">
        <div class="card">
            <div class="row">
               <h2>{{ $route.params.id }}</h2>  
               <h2>{{ $route.params.name }}</h2>    
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        name: "ProjectsDetail",
        props: {
                id: {
        required: true,
        type: String
    }
},
    }
</script>

My problem is : i can get the only the id, but i want to get also the name and all other value of my json component. Thank you for your help.

0 likes
17 replies
codebullet's avatar

what I see you are passing params of params: { id: project.id, project: project }}

in your Project detail page you are accepting only the id as String type

<template>
    <div class="container" style="padding: 6rem 0px;">
        <div class="card">
            <div class="row">
               <h2>{{ $route.params.id }}</h2>  
               <h2>{{ $route.params.name }}</h2>    
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        name: "ProjectsDetail",
        props: {
                id: {
        required: true,
        type: String
    },

// Accept project as Object
		project: {
					required: true, 
					type: Object
			}
},
    }
</script>

I think passing project to project detail page and accepting as Object will have the id, no need passing id again

Rod2rick's avatar

@codebullet I tried your code, but, it only retrieves the id and the other elements, such as name, type.. are not displayed. Also, it does not return any error in the vuejs console of the navigator. What is the best way to retrieve data from my json data knowing that an object has a component (id, name, type, location...) Thanks in advance for your suggestions. PS : I use Vue 3.0 and Router 4.0

Hiz's avatar

@Rod2rick How do you try to access the passed props on the product detail page?

Have you tried accessing your project properties like this?

    <h2>{{ $route.params.id }}</h2>  
     <h2>{{ project.name }}</h2>    
Rod2rick's avatar

@Hiz i have try <h2>{{ project.name }}</h2> but i get this error on the console navigation TypeError: can't access property "name", $props.project is undefined.

Rod2rick's avatar

@Hiz I have posted it from the beginning. the code bellow Product Detail Page is my detail page.

Hiz's avatar

@Rod2rick Alright I couldn't find a clean solution, but if you pass the object directly into the params like so:

params: { id: project.id, project: project }

It will actually pass the object as a string '[object Object']. So you won't be able to use it at all. A different solution is to use the spread operator.

Product list page file

    :to="{
      name: 'projects-detail',
      params: { id: project.id, ...project },
    }"

If you pass the project with the spread operator you will be able to access the data in your product detail page like this:

Product detail page

   <div class="row">
        <h2>{{ $route.params.price }}</h2>
        <h2>{{ $route.params.title }}</h2>
     </div>

Live example

Once again I don't know if this is the correct way but it works.

Rod2rick's avatar

@hiz I updated with the changes you suggested. The components display well. But when I refresh the page, only the id shows. Also in the codesandbox, when I refresh, the other elements disappear.

Hiz's avatar

@Rod2rick That is because when you go to the detail page it will pass the data into the $route.params. But if you refresh the page that data you passed is gone because it's not actually storing the data anywhere. So vue doesn't know where to get the data from when you are refreshing the page. Vue only knows to where the id is because it is present in url projects/1.

Rod2rick's avatar

@hiz. OK, I see. So what would be the best method to pass objects from one vue to another, without having to lose them when refreshing the page. This stuff has been bugging me for at least 2 weeks. Please help me. Thanks in advance.

Hiz's avatar

@Rod2rick Alright one solution is to pass the data as a query string to the other page. What that means is that the project detail page is able to read your data from the url and if you refresh the page vue will get the data from the url once again.

Passing the data as a query

  <router-link
    :to="{
      name: 'projects-detail',
      params: { id: project.id },
      query: { ...project },
    }"
  >

Getting the query data on the product detail page

     <h2>{{ $route.query.price }}</h2>
        <h2>{{ $route.query.title }}</h2>

Live example

Rod2rick's avatar

@Hiz. Thank you very much for your assistance. This time it's good, I recover the data and in addition when I refresh the data is kept and displayed. Furthermore, I would like to learn in depth what I have done. Is there a drawback in the method I used to pass the data if so which one? Could there be a better method for performing this task? Thanks in advance.

Hiz's avatar

@Rod2rick On the background the vue router does some magic and transforms your data into a query string and appends it to the url.

https://yourdomain.com/project/1?title=refactor&price=4&date=2020

After vue has arrived on the page vue router allows you the interact with the query string as a object trough the route $route object. You can read the query parameters from that object. Some more info on query strings

   <h2>{{ $route.params.price }}</h2>

The draw back from this:

1: Your urls can be come very long because it has all the data you want to be displayed on the product detail page.

2: If person A sends the url to person B and person A makes changes to the url. The page url will display the changes made by person A and potentially some malicious changes could be made.

A better method would be to retrieve the data by the id from some datasource (a simple json file or database).

<script>
import projectsJson from './json/projects.js'
export default {
  name: "App",
  components: {},
    data() {
      return {
        projects: projectsJson,
        currentProject: null,
      }
    },
     mounted() {
      const projectId = this.$route.params.id
      this.project = this.projects[projectId ]
    }
};
</script>
Rod2rick's avatar

@Hiz. Thank you very much for the explanations. I would like to try the code sent. Should it be used on the productDetail or productList.

Rod2rick's avatar

@hiz unfortunatly I test the code and it doesn't work. What is the best way to have a route with less informations like product/id

Thanks in advance

Rod2rick's avatar
Rod2rick
OP
Best Answer
Level 1

Here is what I finally did :

-Step 1 In the data json file, add an specific id named uuid

{
      id: 1,
      name: 'Product name',
      price: 0.33,
      image: require('@/assets/prroduct_image001.jpg'),
      description:  'First version of the product description...',
      uuid: 'project-001' // pay attention to this line - line for specific id
    },

-Step 2 In the projectDetail.vue, create an computed property

computed: {
    infoProject() {
      const id = this.$route.params.id;
      const project = this.projects.find((p) => p.uuid == id);
      return project;
    },

-Step 3 In the projectDetail.vue, change the data to display by this

<ul>
  <li>{{ infoProject.name }} - {{ infoProject.price }} <!-- and etc ... {{ infoProject.image }}  --></li>
</ul>

-Step 4 In the projectList.vue, changed the router-link to this

<router-link :to="{ name: 'projects-detail', params: { id: project.uuid }}">{{ project.name}}</router-link> 

-Step 5 here is the code for index.js

 {
        path: '/:id/detail',
        name: 'projects-detail',
		component: () =>
			import(/* webpackChunkName: "projects" */ '../views/ProjectsDetailPage.vue'),
		meta: {
			title: Project-Détail page',
		},
        props: true
    }, 

After all this change, you can get the informations detail of a project and avoid a long link so link will be /uuid/detail

1 like

Please or to participate in this conversation.