Skip to content
Advertisement

Passing a prop as a prop to another component using vue router-link

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:

  1. use any approach for state management as described in official documentation so both PageViewRecipe and RecipeCard can have an access to the same list of recipes.

  2. In PageViewRecipe pass id 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>
  1. 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.

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement