74

Suppose I have a Vue.js component like this:

var Bar = Vue.extend({
    props: ['my-props'],
    template: '<p>This is bar!</p>'
});

And I want to use it when some route in vue-router is matched like this:

router.map({
    '/bar': {
        component: Bar
    }
});

Normally in order to pass 'myProps' to the component I would do something like this:

Vue.component('my-bar', Bar);

and in the html:

<my-bar my-props="hello!"></my-bar>

In this case, the router is drawing automatically the component in the router-view element when the route is matched.

My question is, in this case, how can I pass the the props to the component?

Robert
  • 31,925
  • 8
  • 35
  • 33

6 Answers6

95
<router-view :some-value-to-pass="localValue"></router-view>

and in your components just add prop:

props: {
      someValueToPass: String
    },

vue-router will match prop in component

lukpep
  • 1,559
  • 1
  • 11
  • 18
  • 2
    @lukpep I have run into something similar, when I bind my prop on ``, I got the following error `Attribute ":my_prop" is ignored on component because the component is a fragment instance`. Any idea what's wrong? – highFlyingSmurfs Oct 05 '16 at 07:49
  • 5
    This may be a bad idea. what happens when user comes directly via URL ? – shakee93 Dec 09 '16 at 19:28
  • 38
    Also, wouldn't this prop be getting passed to all routed components and not just those who actually use it? – Shai May 29 '17 at 07:46
  • 6
    So how does one actually achieved the desired outcome as asked? – The Condor Jan 02 '18 at 10:41
  • 1
    Why is this not working on a clean basic Vue app (two components one child route)? Vue-Router doesn't pass the attribute defined on router-view as a props variable but as html attribute in my case... – FullStack Alex Dec 15 '19 at 22:35
46

sadly non of the prev solutions actually answers the question so here is a one from quora

basically the part that docs doesn't explain well is

When props is set to true, the route.params will be set as the component props.

so what you actually need when sending the prop through the route is to assign it to the params key ex

this.$router.push({
    name: 'Home',
    params: {
        theme: 'dark'
    }
})

so the full example would be

// component
const User = {
  props: ['test'],
  template: '<div>User {{ test }}</div>'
}

// router
new VueRouter({
  routes: [
    { 
      path: '/user',
      component: User,
      name: 'user',
      props: true 
    }
  ]
})

// usage
this.$router.push({
    name: 'user',
    params: {
        test: 'hello there' // or anything you want
    }
}) 
ctf0
  • 6,991
  • 5
  • 37
  • 46
  • 2
    Does it mean that this can only be achieved with named routes? – Alen Siljak May 11 '19 at 17:16
  • 1
    no https://router.vuejs.org/guide/essentials/navigation.html#router-push-location-oncomplete-onabort, but its better to use named routes "easier to maintain" – ctf0 May 12 '19 at 09:25
13

In the router,

const router = new VueRouter({
  routes: [
    { path: 'YOUR__PATH', component: Bar, props: { authorName: 'Robert' } }
  ]
})

And inside the <Bar /> component,

var Bar = Vue.extend({
    props: ['authorName'],
    template: '<p>Hey, {{ authorName }}</p>'
});
Jegadesh B S
  • 689
  • 1
  • 6
  • 14
5

This question is old, so I'm not sure if Function mode existed at the time the question was asked, but it can be used to pass only the correct props. It is only called on route changes, but all the Vue reactivity rules apply with whatever you pass if it is reactive data already.

// Router config:
components: {
  default: Component0,
  named1: Component1
},
props: {
  default: (route) => {
    // <router-view :prop1="$store.importantCollection"/>
    return {
      prop1: store.importantCollection
    }
  },
  named1: function(route) {
    // <router-view :anotherProp="$store.otherData"/>
    return {
      anotherProp: store.otherData
    }
  },
}

Note that this only works if your prop function is scoped so it can see the data you want to pass. The route argument provides no references to the Vue instance, Vuex, or VueRouter. Also, the named1 example demonstrates that this is not bound to any instance either. This appears to be by design, so the state is only defined by the URL. Because of these issues, it could be better to use named views that receive the correct props in the markup and let the router toggle them.

// Router config:
components:
  {
    default: Component0,
    named1: Component1
  }
<!-- Markup -->
<router-view name="default" :prop1="$store.importantCollection"/>
<router-view name="named1" :anotherProp="$store.otherData"/>

With this approach, your markup declares the intent of which views are possible and sets them up, but the router decides which ones to activate.

Alicia Sykes
  • 5,997
  • 7
  • 36
  • 64
jimp
  • 16,999
  • 3
  • 27
  • 36
  • Thanks so much for this. The documentation should definitely contain example with components and function mode, the usage differs from usage with single "component". Anyways I kind of hate having component and components options with slightly different syntax because of emergent requirements. – ooouuiii Jan 31 '21 at 22:27
  • named views seems like what I need but I get a linting error 'The template root requires exactly one element' Do you happen to know a fix for this? – KKS Sep 14 '21 at 13:55
  • You need to wrap your template code in exactly one element, like a `
    `.
    – jimp Sep 14 '21 at 18:39
1
 const User = {
      props: ['id'],
      template: '<div>User {{ id }}</div>'
    }
    const router = new VueRouter({
      routes: [
        { path: '/user/:id', component: User, props: true }

        // for routes with named views, you have to define the props option for each named view:
        {
          path: '/user/:id', 
          components: { default: User, sidebar: Sidebar },
          props: { default: true, sidebar: false }
        }
      ]
    })

Object mode

const router = new VueRouter({
  routes: [
    { path: '/promotion/from-newsletter', component: Promotion, props: { newsletterPopup: false } }
  ]
})

That is the official answer. link

aboutqx
  • 418
  • 5
  • 18
  • 8
    In this situation, where would one actually pass in the string "hello", as was asked? – mcheah Dec 06 '17 at 17:48
  • 1
    Reading further in the official docs: "When props is set to true, the route.params will be set as the component props." The author was asking how to set a custom value "hello" – tgf Jan 25 '18 at 00:15
  • 29
    I love when people just copy and paste official documentation that doesn't answer the question. We have all seen the official documentation and it doesnt answer OP's question, so pasting it again with no explanation or clarification and walking away does not add value to the post. – jacurtis Jun 28 '18 at 23:31
  • 1
    is there a way to pass bind data array that is defined in the app.data? (`new Vue({ data: ...`) – stallingOne Jul 23 '18 at 20:15
-1

Use:

this.$route.MY_PROP

to get a route prop