Reputation: 55
I have a parent component with the following line
<router-view :product-id="productId" :data-source="attributes"></router-view>
depending on the context it renders one of the two components defined in the router config
path: 'parent',
component: Parent,
children:
[
{
path: 'edit',
component: Edit,
children:
[
{
path: 'attribute/:id',
component: Attribute,
}
]
},
{
path: 'grid',
component: Grid,
}
]
The thing is that the product-id and data-source props are available only in the Edit and Grid components. I'd like to have them available in the Attribute component as well as the Edit component is just a background with some static text (common for many components).
As a workaround I've created a propertyBag prop in the Edit component that passes an object down. That's the way I use it in the parent component
<router-view :property-bag="{ productId:productId, dataSource:dataSource, ...
and the Edit component
<router-view :property-bag="propertyBag"></router-view>
Is there a simpler way to achieve it ?
Upvotes: 3
Views: 11712
Reputation: 2617
You must pass all data via props to children components. You don't have to pass it as an object but Vue.js does require all data to be passed to children. From their documentation:
Every component instance has its own isolated scope. This means you cannot (and should not) directly reference parent data in a child component’s template. Data can be passed down to child components using props.
So you are doing it in the correct manner. You don't have to create an object, you are able to pass as many props as you would like but you do have to pass the from each parent to each child even if the parent is a child of the original "parent".
Upvotes: 0
Reputation: 1001
Vue $attrs is the new way to propagate props
From the Docs:
vm.$attrs
Contains parent-scope attribute bindings (except for class and style) that are not recognized (and extracted) as props. When a component doesn’t have any declared props, this essentially contains all parent-scope bindings (except for class and style), and can be passed down to an inner component via
v-bind="$attrs"
- useful when creating higher-order components.
For more information, see Vue.js API Reference - $attrs
Upvotes: 9
Reputation: 35684
You have to declare the props and bind them to pass them to the child. Have a look at https://v2.vuejs.org/v2/api/#v-bind for available options
specifically, this may be of interest
<!-- binding an object of attributes -->
<div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>
<!-- but you can also... -->
<div v-bind="allProps"></div>
This means you can pass down the object, and have the child parse the appropriate props. This means that the child has to have the props defined in order to catch them. So what you may be able to do is, in the case of the parent, have :propBag="propBag"
and inside edit, pass down v-bind="propBag"
, and that will use the correct props at the child level
Upvotes: 2
Reputation: 749
for vue > 2.0
v-bind="$attrs"
it's sufficient, or you can declare them at data()
, with [this.$attrs]
Upvotes: 2
Reputation: 819
Use case: Props that you only need on the n-th child components, you can simply forward downstream without having to define the same props all over again in each component.
Correction: v-bind="$attrs"
works just fine. Just make sure the parent also uses v-bind="$attrs"
and not v-bind="$attr"
('s' was missing) which was the error that made me think v-bind="{ ...$attrs }" was needed.
However, I think you should still be able to use v-bind="{ ...$attrs }"
to access all previous attributes, even if parents didn't explicitly propagated them.
How to:
Based on Alexander Kim's comment, it must be v-bind="{ ...$attrs }"
.
...
is needed to pass the attributes of the previous component (parent) as $attrs
only passes the attributes of the current component.
v-bind="{ ...$attrs }"
Upvotes: 0
Reputation: 817
Solution possible from Vue 2.2.0
provide / inject
This pair of options are used together to allow an ancestor component to serve as a dependency injector for all its descendants, regardless of how deep the component hierarchy is, as long as they are in the same parent chain.
https://fr.vuejs.org/v2/api/index.html#provide-inject
Upvotes: 0
Reputation: 5408
Have you looked at vuex. It's really quite easy to use and allows you to store data for your entire app in a single data store. This means you don't have to keep passing data through props, you can just access variables set in the store.
Here is a link to vuex docs (What is Vuex) https://vuex.vuejs.org
Upvotes: 3