2

I have 3 files: App, BlogList, BlogItem. I want to allow the user to delete the post if she/he wants to. I am using splice but for some reason, I get this error:

Property or method "removePost" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property.

Here are the code snippets(BlogList is included in the App and also consists of many BlogItems):

App:

<template>
  <div id="app">
    <Header />
    <PostList v-bind:posts="posts" />
  </div>
</template>

<script>
import axios from "axios";
import Header from ...
import PostList from ...

export default {
  name: "App",
  components: {
    Header,
    PostList,
  },
data() {
    return {
      posts: []
    };
  }
};
</script>

BlogList:

<template>
<div class="blog-list">
    <div v-for="(post,index) in posts" v-bind:key="post.id">
      <PostItem v-bind:post="[post,index]" />
    </div>
</div>
</template>

<script>
import PostItem from ...

export default {
  name: "PostList",
  components: {
    PostItem
  },
  props: ["posts"],
  methods: {
    removePost: function(index) {
      this.$delete(this.posts, index);
    }
  }
};
</script>

BlogItem:

<template>
  <div class="wrapper">
    <div class="post-text">{{post.data.title}}</div>
      <button class="btn-remove" @click="removePost(index)">Remove</button>
    </div>
  </div>
</template>

<script>
export default {
  name: "PostItem",
  props: ["post"]
};
</script>

I am still fairly new to Vue and passing the data between the components seems is a challenge. I tried declaring the function in BlogList as it is where I put my v-for but I cannot fetch the index of the blog post's clicked(and I believe that is what causes issues). I'm including only the necessary bits of code and I am aware that a similar question has been asked already (How to remove an item from an array in Vue.js) but in my case, I want to use 3 separate components instead of just one.

Nikola Kirincic
  • 3,651
  • 1
  • 24
  • 28
priortt
  • 129
  • 11

1 Answers1

1

You have defined removePost in the BlogList, but not in the BlogItem component, that is why it throws an error. Also, there is no index within the BlogItem component's scope. In your scenario, it would be best to either emit the event or use the <slot>.

<template>
  <div class="wrapper">
    <div class="post-text">{{this.post.data.title}}</div>
      <button class="btn-remove" @click="removePost(this.index)">Remove</button>
    </div>
  </div>
</template>

<script>
export default {
  name: "PostItem",
  props: ["post", "index"],
  methods: {
    removePost(index){
     this.$emit('remove-post', index);

    }

  }
};
</script>

And then in the PostList component, catch the event within created() and call the parent's removePost:

<template>
<div class="blog-list">
    <div v-for="(post,index) in posts" v-bind:key="post.id">
      <PostItem v-bind:post="[post,index]" />
    </div>
</div>
</template>

<script>
import PostItem from ...

export default {
  name: "PostList",
  components: {
    PostItem
  },
  props: ["posts"],
  created(){
    this.$root.$on('remove-post', function(index){
      this.removePost(index);
    });
  },
  methods: {
    removePost: function(index) {
      this.$delete(this.posts, index);
    }
  }
};
</script>
Nikola Kirincic
  • 3,651
  • 1
  • 24
  • 28