What I want: I have two components, the parent component (Wall.vue) and the child component (PostItem.vue). Every PostItem
has a delete button. On click, a request to my API is sent and the item gets deleted from the database. Then I want to call the getPosts
function of the parent component to get all the posts again (this time without the deleted post).
The Problem: Inside the child component, I have no access to the this.$parent
Object (or more specific, it's just empty and doesn't contain the functions), so I can't call the getPosts
-Function. When I remove the <transition-group>
in the parent component that surrounds also the child-component, everything works fine.
What is the problem here?
template-portion:
<template>
<div class="Wall view">
<transition-group name="wallstate">
<template v-else-if="messages">
<PostItem
v-for="(message, index) in messages"
:key="index"
:message="message"
:index="index"
class="PostItem"
/>
</template>
<h1 v-else>
Could not load messages. Please try later.
</h1>
</transition-group>
</div>
</template>
script-portion:
<script>
import { mapGetters } from 'vuex';
import { postsAPI } from '../services/posts.service.js';
import PostItem from '../components/PostItem.vue';
export default {
components: {
PostItem,
},
data() {
return {
messages: null,
};
},
methods: {
getPosts() {
///////Do stuff
}
}
};
</script>
template-portion
<template>
<div class="PostItem__message frosted">
<p class="PostItem__messageContent">{{ message.content }}</p>
<p>
by: <strong>{{ message.user.username }}</strong>
</p>
<a
@click="deletePost"
:data-id="message._id"
v-if="message.user._id === user.id"
>
Delete
</a>
</div>
</template>
script-portion:
<script>
import { postsAPI } from '../services/posts.service.js';
import { mapGetters } from 'vuex';
export default {
name: 'PostItem',
props: {
message: {
type: Object,
required: true,
},
index: {
type: Number,
required: true,
},
},
computed: {
...mapGetters({
user: 'auth/user',
}),
},
methods: {
deletePost(e) {
const id = e.target.dataset.id;
postsAPI.removeOne(id).then((res) => {
this.$parent.getPosts(); <-------- PROBLEM HERE
});
},
},
};
</script>
It's generally considered a bad practice to use this.$parent
(it couples the components and reduces encapsulation / code clarity.) The child component should emit an event when it wants to send information to an ancestor component.
Remove the direct access and $emit
an event called 'deleted':
deletePost(e) {
const id = e.target.dataset.id;
postsAPI.removeOne(id).then((res) => {
this.$emit('deleted'); // Emitting the event
});
},
The parent should listen for that deleted
event and run an event handler:
<PostItem
v-for="(message, index) in messages"
:key="index"
:message="message"
:index="index"
class="PostItem"
@deleted="getPosts"
/>
The parent will call the getPosts
method when triggered by the @deleted
event listener.
inside the methods part, instead of :
methods: {
deletePost(e) {
const id = e.target.dataset.id;
postsAPI.removeOne(id).then((res) => {
this.$parent.getPosts();
});
},
},
you may try this:
methods: {
deletePost(e) {
const id = e.target.dataset.id;
let self=this;
postsAPI.removeOne(id).then((res) => {
self.$parent.getPosts();
});
}
Because of the scope chain, 'this' inside .then() does not point to the same variable environment as variable 'self' does. So perhaps it's the reason it fails to work.
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