I am using Vue.js 2.
I have a problem with passing value to the child component as a prop. I am trying to pass card
to card-component
.
In card-component
I can access the prop in the Card goes here {{card}}
section.
However when I try to access it in created
or mounted
methods it's undefined
.
Parent:
<template>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<card-component :card="place.card"></card-component>
</div>
</div>
</div>
</template>
<script>
import CostComponent from './CostComponent';
import CardComponent from './CardComponent';
export default {
components: {
CostComponent, CardComponent
},
props: ['id'],
data() {
return {
place: []
}
},
created() {
axios.get('/api/places/' + this.id)
.then(response => this.place = response.data);
}
}
</script>
Child:
<template>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<ul class="list-unstyled">
Card goes here {{card}}
</ul>
</div>
</div>
</div>
</template>
<script>
import CardItemComponent from './CardItemComponent';
export default {
components: {
CardItemComponent
},
props: ['card'],
created() {
console.log(this.card); // undefined
},
mounted() {
console.log(this.card); // undefined
},
}
</script>
I did a lot of googling but none of the solutions I found have fixed my issue.
This is purely a timing issue. Here's what happens...
place
(this is also a problem but I'll get to that later). An async request is startedYour parent component creates a CardComponent
instance via its template
<card-component :card="place.card"></card-component>
at this stage, place
is still an empty array, therefore place.card
is undefined
CardComponent
created
hook runs, logging undefined
CardComponent
is mounted and its mounted
hook runs (same logging result as created
)place
from an empty array to an object, presumably with a card
property.card
property is passed down into your CardComponent
and it reactively updates the displayed {{ card }}
value in its template.If you want to catch when the card
prop data changes, you can use the beforeUpdate
hook
beforeUpdate () {
console.log(this.card)
}
Vue.component('CardComponent', {
template: '<pre>card = {{ card }}</pre>',
props: ['card'],
created () {
console.log('created:', this.card)
},
mounted () {
console.log('mounted:', this.card)
},
beforeUpdate () {
console.log('beforeUpdate:', this.card)
}
})
new Vue({
el: '#app',
data: {
place: {}
},
created () {
setTimeout(() => {
this.place = { card: 'Ace of Spades' }
}, 2000)
}
})
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">
<card-component :card="place.card" />
</div>
See https://vuejs.org/v2/guide/instance.html#Lifecycle-Diagram
If place
is meant to be an object, you should not be initialising it as an array. Also, if your CardComponent
relies on data being present, you may want to conditionally render it.
For example
data () {
return { place: null }
}
and
<card-component v-if="place" :card="place.card"></card-component>
then CardComponent
will only be created and mounted after place
has data.
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