I cannot pass data from parent to child. I am using props, have tried returning data as well - no luck. I have a panel component (which is parent) with data and panelBody component (child)
Panel is as follows:
<template> <div id="panel"> <div class="panel"> <ul> <li v-for="shelf in shelfs"> <panel-body :shelf="shelf" :selected.sync="selected"></panel-body> </li> </ul> </div> </div> </template> <script> import PanelBody from '../components/PanelBody' export default { name: 'panel-body', components: { 'panel-body': PanelBody }, data: () => ({ shelfs: [{ name: 'shelf 1', books: [{ title: 'Lorem ipum' }, { title: 'Dolor sit amet' }] }, { name: 'shelf 2', books: [{ title: 'Ipsum lorem' }, { title: 'Amet sit dolor' }] }], selected: {} }) } </script> <style scoped> a { color: #42b983; } </style>
My panelBody is:
<template> <div id="panel-body"> <a href="#" v-on:click.prevent.stop="select">{{ shelf.name }}</a> <ul v-show="isSelected"> <li v-for="book in shelf.books">{{ book.title }}</li> </ul> </div> </template> <script> export default { name: 'panel-body', props: ['shelf', 'selected'], computed: { isSelected: function () { return this.selected === this.shelf } }, methods: { select: function () { this.selected = this.shelf } } } </script> <style scoped> a { color: #42b983; } </style>
Please help! Can't figure out the error "vue.esm.js?65d7:3877 Uncaught RangeError: Maximum call stack size exceeded". WHen I remove the data everything works like it should.
The reason you have the error
Maximum call stack size exceeded
is because of this
import PanelBody from '../components/PanelBody' export default { name: 'panel-body', components: { 'panel-body': PanelBody },
You defined your Panel component with name: 'panel-body'
. Change that to name: 'panel'
, and you will remove your circular reference.
The other issues mentioned in comments and the other answer generally apply as well. Here are working versions of your components.
Panel.vue
<template> <div id="panel"> <div class="panel"> <ul> <li v-for="shelf in shelfs"> <panel-body :shelf="shelf" :key="shelf.name" :selected.sync="selected"></panel-body> </li> </ul> </div> {{selected}} </div> </template> <script> import PanelBody from './PanelBody.vue' export default { name: 'panel', components: { 'panel-body': PanelBody }, data(){ return { shelfs: [{ name: 'shelf 1', books: [{ title: 'Lorem ipum' }, { title: 'Dolor sit amet' }] }, { name: 'shelf 2', books: [{ title: 'Ipsum lorem' }, { title: 'Amet sit dolor' }] }], selected: {} } } } </script> <style scoped> a { color: #42b983; } </style>
PanelBody.vue
<template> <div id="panel-body"> <a href="#" v-on:click.prevent.stop="select">{{ shelf.name }}</a> <ul v-show="isSelected"> <li v-for="book in shelf.books">{{ book.title }}</li> </ul> </div> </template> <script> export default { name: 'panel-body', props: ['shelf', 'selected'], data(){ return { internalSelected: null } }, computed: { isSelected: function () { return this.internalSelected === this.shelf } }, methods: { select: function () { this.internalSelected = this.shelf this.$emit("update:selected", this.internalSelected) } } } </script> <style scoped> a { color: #42b983; } </style>
I wanted to note one more thing. Because of this line in PanelBody, this.selected = this.shelf
Vue will throw a warning that you are mutating a prop directly. Generally you should store a local copy of a property that you are going to mutate. I've updated the code above to do that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With