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.
The name of the Vue you are in should not equal the name of the component you are importing.
In my case
<template>
<div>
<SingleStandard></SingleStandard>
</div>
</template>
<script>
import SingleStandard from '../components/SingleStandard';
export default {
name: 'SingleStandard',
components: { SingleStandard },
};
</script>
The above code was causing the same issue, but when i changed the name of the exported component it worked.
<template>
<div>
<SingleStandard></SingleStandard>
</div>
</template>
<script>
import SingleStandard from '../components/SingleStandard';
export default {
name: 'SingleStandardView', <-------------
components: { SingleStandard },
};
</script>
Please check your naming conventions for all future people :)
the sync has changed in vue2.
https://vuejs.org/v2/guide/components.html#sync-Modifier
you should use it this way
<panel-body :shelf="shelf" :selected="selected" @update:selected="val => selected = val"></panel-body>
and on child
this.$emit('update:selected', shelf)
OR
you could do just this
<panel-body :shelf="shelf" :selected="shelf == selected" @select="selected = shelf"></panel-body>
and on child
this.$emit("select")