Reputation: 167
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>
Upvotes: 4
Views: 4396
Reputation: 11
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.
Upvotes: 1
Reputation: 63119
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.
Upvotes: 4