Skip to content
Advertisement

Vue.js on render populate content dynamically via vue.router params

AS title sates, I don’t so much need a solution but I don’t understand why I’m getting the undesired result;

running v2 vue.js

I have a vue component in a single component file.

Basically the vue should render data (currently being imported from “excerciseModules” this is in JSON format).

IT’s dynamic so based on the url path it determines what to pull out of the json and then load it in the page, but the rendering is being done prior to this, and I’m unsure why. I’ve created other views that conceptually do the samething and they work fine. I dont understand why this is different.

I chose the way so I didn’t have to create a ton of routes but could handle the logic in one view component (this one below).

Quesiton is why is the data loading empty (it’s loading using the empty “TrainingModules” on first load, and thereafter it loads “old” data.

Example url path is “https…../module1” = page loads empty

NEXT

url path is “https…./module 2” = page loads module 1

NEXT

url path is “https…./module 1” = page loads module 2

//My route
{

        path: '/excercises/:type',
        name: 'excercises',
        props: {
        },
        component: () => import( /* webpackChunkName: "about" */ '../views/training/Excercises.vue')
    }

<template>
<div class="relatedTraining">
    <div class="white section">
        <div class="row">
            <div class="col s12 l3" v-for="(item, index) in trainingModules" :key="index">
                <div class="card">
                    <div class="card-content">
                        <span class="card-title"> {{ item.title }}</span>
                        <p>{{ item.excercise }}</p>
                    </div>
                    <div class="card-action">
                        <router-link class="" to="/Grip">Start</router-link>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
</template>
<script>
    console.log('script');
    let trainingModules; //when initialized this is empty, but I would expect it to not be when the vue is rendered due to the beforeMount() in the component options. What gives?
/* eslint-disable */
let init = (params) => {
    console.log('init');
    console.log(trainingModules);
    trainingModules = excerciseModules[params.type];
   

    //return trainingModules
    
}
import { getRandom, randomImage } from '../../js/functions';
import { excerciseModules } from '../excercises/excercises_content.js'; //placeholder for JSON
export default {
    name: 'excercises',
    components: {
    },
    props: {
    },
    methods: {
        getRandom,
        randomImage,
        init
    },
    data() {
        return {
            trainingModules,
        }
    },
    beforeMount(){
        console.log('before mount');
        init(this.$route.params);
    },
    updated(){
        console.log('updated');
        
    },
    mounted() {
        
        console.log('mounted');
        //console.log(trainingModules);
    }
}

</script>


Advertisement

Answer

I can’t tell you why your code is not working because it is an incomplete example but I can walk you through a minimal working example that does what you are trying to accomplish.

The first thing you want to do, is to ensure your vue-router is configured correctly.

export default new Router({
  mode: "history",

  routes: [
    {
      path: "/",
      component: Hello
    },
    {
      path: "/dynamic/:type",
      component: DynamicParam,
      props: true
    }
  ]
});

Here I have a route configured that has a dynamic route matching with a parameter, often called a slug, with the name type. By using the : before the slug in the path, I tell vue-router that I want it to be a route parameter. I also set props: true because that enables the slug value to be provided to my DynamicParam component as a prop. This is very convenient.

My DynamicParam component looks like this:

<template>
  <div>
    <ul>
      <li v-for="t in things" :key="t">{{ t }}</li>
    </ul>
  </div>
</template>

<script>
const collectionOfThings = {
  a: ["a1", "a2", "a3"],
  b: ["b1", "b2"],
  c: [],
};

export default {
  props: ["type"],
  data() {
    return {
      things: [],
    };
  },
  watch: {
    type: {
      handler(t) {
        this.things = collectionOfThings[t];
      },
      immediate: true,
    },
  },
};
</script>

As you can see, I have a prop that matches the name of the slug available on this component. Whenever the ‘slug’ in the url changes, so will my prop. In order to react to those changes, I setup a watcher to call some bit of code. This is where you can make your fetch/axios/xhr call to get real data. But since you are temporarily loading data from a JSON file, I’m doing something similar to you here. I assign this data to a data value on the component whenever the watcher detects a change (or the first time because I have immediate: true set.

I created a codesandbox with a working demo of this: https://codesandbox.io/s/vue-routing-example-forked-zesye

PS: You’ll find people are more receptive and eager to help when a minimal example question is created to isolate the problematic code. You can read more about that here: https://stackoverflow.com/help/minimal-reproducible-example

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