How to pass data between two components in Vue?

Good afternoon.

Deal with Vue and want to make your component that will make a universal mechanism for display forms and edit/add the values in the table (and any other forms). Briefly, the component looks like this:

template.vue
<pages :currentPage.sync="currentPage" >
 <page name="index" title='project List'>
 <template slot="toolbar">
 <v-btn color="primary" dark class="mb-2" @click="newProject">New project</v btn>
</template>
<v-data-table
:headers="headers"
:items="projects"
hide-actions
class="level-1"
>
....
</v-data-table>
</page>
 <page parent="index" name="edit" title='Edit'>
....
</page>
</pages>


pages.vue
<template>
 <v-card width="100%" class="flexcard">
 <v-card-title primary-title>
 <v-breadcrumbs divider="/" class="pa-0">
....
</v breadcrumbs>
<v-spacer></v spacer>
 <v-card ref="toolbar">
 ......here it is necessary to insert the slot toolbar of the child component's page
</v-card>
</v-card-title>
 <v-card-text class="grow">
<slot></slot>
</v-card-text>
<v-card-actions>
<v-spacer></v spacer>
</v-card-actions>
</v-card>
</template>


page.vue
<template>
the <div>
 <div v-if="name==pagesActive">
 <slot name="toolbar"></slot>
<slot></slot>
</div>
</div>
</template>

the <script>
 export default {
 data: () => ({

}),
computed:{
 pagesActive () {
 return this.$parent.$parent.activePage
}
},

 created () {
..here I would like to access a parent component and its slot
 // this.$parent.$refs.toolbar = '123123'
}
}
</script>


a bunch of articles already read that the transfer from parent to child is very difficult. I need to pass not just values but preferably the entire slot='toolbar' from the page.vue in the parent element to pages.vue.

Yes I can get to this element of the page.this vue.$parent.$children.find .... but the bigger question is how. Can I organize my logic or is it overkill and all have to constantly copy from page to page.

I want to eventually get:
Universal component that will allow one router to build a few pages. Ie there will be several pages: a list of projects, editing/adding a project, the edit additional project settings. I want it to be done beautifully using bread crumbs, etc. (now, in principle, already all sold) but I want to use the space of the parent component pages.vue to put in controls for a particular page.

Why would I do that. I want to limit myself from writing the model code, page layout, header, breadcrumbs, controls in the header and in the basement of a form, common variables (because the adding/editing and displaying of the table is essentially one form, but I want to make her beautiful)
March 12th 20 at 08:03
1 answer
March 12th 20 at 08:05
If anyone is interested, I implemented this task. All executable code and the template had to be moved to a component Page.vue

Here is the code listing:
Pages.vue
<template>
 <div style="width: 100%; height: 100%">
<slot></slot>
</div>
</template>

<style>
 .flexcard {
 display: flex;
 flex-direction: column;
}
</style>

the <script>
 export default {
 data: () => ({
 pages : []
}),
 mounted () {
this.initPages()
},
 methods: {
 initPages() {
 this.$children.forEach((child) => {
 if (child.$options.name == 'Page'){
this.pages.push(child)
}
})
},
}
}
</script>


Page.vue
<template>
 <v-card width="100%" class="flexcard" v-if="name==activePage" style="height: 100%">
 <v-card-title primary-title style="padding-bottom: 0; padding-top: 0;">
 <slot name="breadcrumbs">
 <v-breadcrumbs divider="/" class="">
<v-breadcrumbs-item
 v-for="item in breadcrumbs"
:key="item.text"
:disabled="item.disabled"
@click.native="activePage=item.page"
class="pa-0"
>
 {{ item.text }}
</v-breadcrumbs-item>
</v breadcrumbs>
</slot>
<v-spacer></v spacer>
 <slot name="toolbar"></slot>
</v-card-title>
 <v-card-text class="grow">
<slot></slot>
</v-card-text>
<v-card-actions>
<v-spacer></v spacer>
 <slot name="actions"></slot>
</v-card-actions>
</v-card>
</template>

the <script>
 export default {
 data: () => ({

}),
computed:{
name(){
 return this.$attrs.name
},
 activePage : {
 get: function () {
 return this.$store.state.activePage
},
 set: function (newValue) {
 this.$store.dispatch('setActivePage', newValue)
}
},
breadcrumbs(){
 if (this.activePage) {
console.log(this.activePage)
 let tap target = this.getBreadcrumb(this.activePage).reverse()
 return tap target
}else{
 return []
}
},
},
methods:{
 getBreadcrumb(pageName) {
 let items = []
 let page = this.getPageByName(pageName)
 if (page) {
items.push({
 text: page.$attrs.title
 page: page.$attrs.name
})
 if (page.$attrs.parent) {
 let parentItem = this.getBreadcrumb(page.$attrs.parent)
 items = items.concat(parentItem)
}
}
 return items
},
getPageByName(name){
 if (this.$parent.pages && this.$parent.pages.length > 0){
 let page = this.$parent.pages.find((p) => {
 return p.$attrs.name == name
})
 return page
}
 return null
},
},
}
</script>


In any file, use the following construction
<template>
 <pages style="height : 100%">
 <vue-element-loading :active="loading" spinner="bar-fade-scale"/>
 <page name="index" title='project List'>
 <template slot="toolbar">
 <v-btn color="primary" small dark class="mb-2" @click.native="newProject">New project</v btn>
</template>
<v-data-table
:headers="headers"
:items="projects"
hide-actions
class="level-1"
>
 <template slot="items" slot-scope="props" disabled="true">
 <td>{{ props.item.name }}</td>
 <td class="justify-center layout px-0">
 <v-flat btn small icon @click="editItem(props.item)">
<v-icon
small

>
edit
</v-icon>
</v btn>

 <v-flat btn small icon color="error"
@click="deleteItem(props.item)"
:loading="props.item.loading"
>
 <v-icon small>
delete
</v-icon>
</v btn>
</td>
</template>
</v-data-table>
</page>
 <page parent="index" name="edit" title='Edit'>
 <v-form v-model="valid">
 <v-layout wrap>
 <v-flex xs12>
 <v-text-field name="name",: error-messages="errors.collect('name')" :rules="nameRules" required v-model="editedItem.name" label="Name"></v-text-field>
</v-flex>
 <v-flex xs12>
<v-spacer></v spacer>
</v-flex>
</v layout>
</v form>
 <template slot="actions">
 <v-small btn @click.native="close">Cancel</v btn>
<v btn
small
:disabled="!valid"
:loading="waitSave"
@click.native="save"
>
Save
</v btn>
</template>
</page>
</pages>
</template>


You can implement breadcrumbs of any level through the chain of parent links in the component page

Find more questions by tags Vue.js