I have a component that takes a list of recipes and creates a component for each item in the array. I am trying to pass the recipe object to a component and then to a second component using Router-Link
<RecipeCard v-for="recipe in filteredRecipes" :key="recipe.id" :recipe="recipe" />
Inside the RecipeCard component looks like this:
<template> <div> <router-link :to="{ path: 'recipe/' + recipe.id, props:{recipe} }"> <div>{{ recipe.title }}</div> <p> {{ recipe.description }} </p> </router-link> </div> </template>
I am trying to pass the recipe to another component so when the recipe card is clicked it opens up a detailed view. After router-link is clicked it directs to this page:
<template> <div> <div>{{recipe.id}}</div> </div> </template> <script> export default { name: 'PageViewRecipe', props: { recipe: { type: Object, required: true } }, data() { return { }; } }; </script> <style></style>
The recipe is an object with more details.
import Vue from "vue"; import Router from "vue-router"; import Home from "./pages/PageHome"; import AddRecipe from "./pages/PageAddRecipe.vue"; import PageViewRecipe from "./pages/PageViewRecipe.vue" Vue.use(Router); const router = new Router({ mode: "history", routes: [ { path: "/", name: 'Home', component: Home, }, { path: "/add-recipe", name: 'AddRecipe', component: AddRecipe, }, { path: "/recipe/:id", name: 'ViewRecipe', component: PageViewRecipe, props: true } ], }); export default router;
Unfortunately, my prop is not passing to the final component. I tried with params, but nothing seems to work.
Advertisement
Answer
The vue-router
doesn’t pass props from <router-link />
to a component being rendered in <router-view />
. Moreover, <router-link />
doesn’t support props
key in to
param. It is just ignored.
What you can do instead is to:
use any approach for state management as described in official documentation so both
PageViewRecipe
andRecipeCard
can have an access to the same list of recipes.In
PageViewRecipe
passid
as a param to router-link. E.g.
<!-- BTW: you don't have to create path by yourself, let vue-router create it for you by combination of named router and params --> <router-link :to="{ name: 'ViewRecipe', params: { id: recipe.id } }"> <div>{{ recipe.title }}</div> <p> {{ recipe.description }} </p> </router-link>
- Inside your
PageViewRecipe
access the list of recipes from the shared place (vuex, shared object, etc) and find the recipe with the id like so:
<template> <div> <div>{{recipe.id}}</div> <p> {{ recipe.description }} </p> </div> </template> <script> export default { name: 'PageViewRecipe', props: { // passed by vue-router (from url), also available as this.$route.params.id id: { type: Number, required: true } }, computed: { recipe() { // `this.recipes` comes from state management (for instance from vuex getter) return this.recipes.find(recipe => recipe.id === this.id); } } } }; </script> <style></style>
The nice thing about this approach is that you make only one API request and since you have an access to the full list of recipes you can handle some edge cases like when recipe with given id doesn’t exist. But you can try to perform two API calls so you don’t have to deal with shared state management.