Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue Router passing props to dynamically loaded children

I'm learning Vue atm, and I'm having trouble getting props passed between children and parent components through Vue Routes. I've got a Layout component, that has a wrapper DIV and looks like this:

<template>
    <div class="container" v-bind:class="cssClass">
      <router-view></router-view>
    </div>
</template>

<script>
export default {
  name: 'Layout',
  props: ['cssClass']
}
</script>

and I've got my routes defined in my base App JS, and looks like the below. So my view on first load has the class "container-animated" and all is good with the world.

const router = new VueRouter({
    routes: [
      { path: '/', component: Layout, props: { cssClass: 'container-animated' },
        children: [
          { path: '', component: Homepage },
          { path: '/hello-world', component: HelloWorldPage, props: { cssClass: '' } }
        ]
     },
    ]
});

However, once I hit the /hello-world route, I want to pass an empty cssClass props to down to Layout, (which HelloWorldPage is currently nested inside) - how would I go about that? Are props even the mechanism to achieve that?

like image 433
Squiggs. Avatar asked Jul 02 '18 17:07

Squiggs.


1 Answers

I figured it out, whether this is the optimum solution for my problem is anyone's guess.

It appears child props aren't picked up automatically by the parent when passed on the Vue Router. So once the components are built / injected dynamically, they each call my custom childinit event, which emits back to the router view defined in the parent (Layout). I set a local variable in the parent to the value of the emitted child, and then bind the class to it.

const router = new VueRouter({
    routes: [
      {
        path: '/',
        component: Layout,
        children: [
          {
            path: '',
            component: Homepage,
            props: { cssClass: 'home' },
          },
          {
              path: '/helloworld',
              component: HelloWorldPage,
              props: { cssClass: 'helloworld' }
          }
        ]
      }
    ]
});

My layout component:

<template>
    <div class="container" v-bind:class="className">
      <router-view v-on:childinit="onChildInit"></router-view>
    </div>
</template>

<script>
export default {
  name: 'Layout',
  props: ['cssClass'],
  data() {
    return {
      className : ''
    }
  },
  methods: {
    onChildInit( value ){
      this.className = value;
    }
  }
}
</script>

My Homepage component:

export default {
  name: 'Homepage',
  props: ['cssClass'],
  created() {
    this.$emit('childinit', this.cssClass);
  }
}

The HelloWorld component emits as well, it's possible that the created method doesn't need to be replicated; might have a go at seeing if you can extend a base component that will always emit on init for both components.

like image 111
Squiggs. Avatar answered Nov 04 '22 01:11

Squiggs.