Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue.js - no access to this.$parent when child component is inside <transition>

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?

Parent-Component (Wall.vue)

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>

Child-Component (PostItem.vue)

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>
like image 236
Michel Avatar asked Oct 20 '25 14:10

Michel


2 Answers

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.

like image 104
Dan Avatar answered Oct 23 '25 04:10

Dan


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.

like image 26
Lizzi Avatar answered Oct 23 '25 04:10

Lizzi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!