Search code examples
imagevue.jshyperlinkroutesdynamic-routing

Dynamic Name Routing / Dynamic Route Matching in VueJS


I have some products that are being iterated over and being displayed. I'd like to use the images of the products as links to the specific page of each individual product. I want each product page to pull from the same template, substituting the props with the appropriate product details.

An example url for a product would be something like: /shop/product/name-of-product

Here is the relevant code:

<template>
    <div class="p-avaible" v-for="item in avaibleProducts" :key="item.name">
        <router-link :to={ name: 'avaibleProducts' , params: { id: 1 }}>
            <img :key="item.image" :src="item.image">
        </router-link>
        <div class="p-name">{{ item.name }}</div>
        <div class="p-price">€{{ item.price }}</div>
        <div class="btn-container">
            <button class="add-to-cart">ADD TO CART</button>
        </div>
    </div>
</template>


<script>
    export default {
      data() {
        return {
          cart: [],
          avaibleProducts: [
            {
              name: "PLASTIC BAGS 3-PACK v1",
              price: 0.33,
              image: require('@/assets/plastic-bag-pack.jpg'),
              description: 'First version plastic bags pack containing 3 HQ assets. Make sure to get yours today.',
              id: 1
            },
            {
              name: "VINYL TEXTURES 2-PACK v1",
              price: 0.22,
              image: require('@/assets/vinyl-texture-pack.jpg'),
              description: 'First version vinyl texture pack containing 2 HQ assets. Make sure to get yours today.',
              id: 2
            },
            {
              name: "STICKER PACK 6-PACK v1",
              price: 0.66,
              image: require('@/assets/sticker-bag-pack.jpg'),
              description: 'First version sticker bag pack containing 6 HQ assets. Make sure to get yours today.',
              id: 3
            }
          ],
        };
      }
    };
</script>

Router/Index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import Shop from '../views/Shop.vue'
import Product from '../views/Product'

Vue.use(VueRouter)

  const routes = [
  {
    path: '/shop',
    name: 'Shop',
    component: Shop
  },
  {
    path: '/product/:id',
    name: Product,
    component: Product
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

Solution

  • hey :)) first you must add a unique property to your product list like a uuid or anything, also you can use id property but its not a good method


    step 1:

    you must add uuid propery to your product object :

    {
          name: 'PLASTIC BAGS 3-PACK v1',
          price: 0.33,
          image: require('@/assets/plastic-bag-pack.jpg'),
          description:
            'First version plastic bags pack containing 3 HQ assets. Make sure to get yours today.',
          id: 1,
          uuid: 'prd-001' // pay attention to this line 
        },
    

    step 2:

    you need to create an computed propery

    computed: {
      showProduct() {
        const id = this.$route.params.id;
        const product = this.avaibleProducts.find((p) => p.uuid == id);
        return product;
      },
    

    step 3:

    and in your template you can access it like this:

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

    step 4:

    you can load single product in this route:

    /product/prd-001
    

    the above route return your first product in your available products state

    step 5:

    change your this line in your Router/Index.js file


    name: Product

    and put it in single quotation like this :

    name: 'Product'

    and change your router-link like this :

    <router-link :to="{name: 'Product' , params:{ id: product.uuid }}">{{ product.name}}</router-link> 
    

    well done!