Trouble with nested components not refreshing correctly within VueJs

I've just started working with Vue and I'm currently developing a forum-style application that allows nested comments. Within this structure, there are two main components: PostForum and Comment. The PostForum component consists of an input box for adding comments and parent Comments. Each individual comment can contain child comments added recursively.

While adding comments works perfectly fine, I've encountered an issue when trying to delete them. Although the AJAX request is sent upon deletion, there seems to be no re-rendering happening on the page. This is how I planned it: when a comment is deleted, I emit a global event that is then listened to in the PostForum component. Upon receiving this event, the corresponding comment is removed from the data. Shouldn't this trigger a re-render of all the comments accordingly? Could someone point out where I might be going wrong?

PostForum.vue

<template>
  <!-- comment box here -->

  <comment
    v-for="(comment, index) in comments" 
    v-if="!comment.parent_id"
    :reply="true" 
    :initialChildren="getChildren(comment.id)" 
    :key="index" 
    :comment="comment">
  </comment>
</template>

<script>
export default {
  data () {
    return {
      comments: [], // all comments
        comment: { // new comment [at comment box]
            body: '',
            parent_id: 0,
        },
    }
  },
  methods: {
    deleteComment (node) {
        axios.delete(`/comments/${node.id}`)
            .then(res => {
                this.comments.splice(node.key, 1)
            })
            .catch(err => {
                console.log(err)
            })
    },
    getChildren: function (parent_id) {
        return this.comments.filter(child => parent_id == child.parent_id)
    },
  },
  mounted: function () {
    window.Event.$on('comment-deleted', (node) => this.deleteComment(node))
  }
}
</script>

Comment.vue

<template>
  <button @click="deleteComment">X</button>

  <!-- comment body goes here -->

  <comment v-for="(child, i) in children" :key="i" :reply="false" :comment="child"></comment>

  <!-- reply form here -->
</template>

<script>
export default {
  props: ['initialChildren']
  data: function () {
    return {
        newComment: {
            body: '',
            parent_id: this.comment.id,
        },
        children: this.initialChildren,
    }
  },
  methods: {
    deleteComment () {
        window.Event.$emit('comment-deleted', {key: this.$vnode.key, id: this.comment.id})
    },
  }
}
</script>

Answer №1

Upon experimentation, I have attempted the following:

The snippet provided serves as a mere illustration to guide you. In my scenario, the child component functions as the comment component in your context. Furthermore, each instance of the child component possesses its own @action listener tailored specifically for that particular child. Consequently, this mechanism empowers it to modify its individual set of children.

You can view a demonstration on codesandbox: https://codesandbox.io/s/qzrp4p3qw9

ParentComponent

<template>
    <div>
        <Child v-for="(children,index) in childrens" :child="children" :key="index" :parent="0" :pos="index"></Child>
    </div>
</template>
import Child from './child'; 
export default {
    data() {
        return {
            childrens:[
                {
                    name:"a",
                    childrens:[
                        {
                            name:'aa',
                        },
                        {
                            name:'ba',
                            childrens:[
                                {
                                    name:'baa',
                                    childrens:[
                                        {
                                            name:'baaa',
                                        },
                                        {
                                            name:'baab',
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                },
                {
                    name:"a",
                    childrens:[
                        {
                            name:'aa',
                        },
                        {
                            name:'ab',
                            childrens:[
                                {
                                    name:'aba',
                                    childrens:[
                                        {
                                            name:'abaa',
                                            childrens:[
                                                {
                                                    name:'baa',
                                                    childrens:[
                                                        {
                                                            name:'baaa',
                                                        },
                                                        {
                                                            name:'baa',
                                                        }
                                                    ]
                                                }
                                            ]
                                        },
                                        {
                                            name:'abab',
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    },
    components:{
        Child
    }
}

ChildComponent

<template>
    <div>
        <div style="padding:5px">
            {{ child.name }}
            <button @click="deleteComment(child)">x</button>
        </div> 
        <child @delete="deleteSubComment" style="padding-left:15px" v-if="typeof child.childrens !== 'undefined'" v-for="(children,index) in child.childrens" :child="children" :pos="index" :key="index" :parent="children.parent"></child>
    </div>
</template>
export default {
    name:"child",
    props:['child','parent',"pos"],
    methods:{
        deleteComment(child) {
            this.$emit('delete',child);
        },
        deleteSubComment(obj) {

            this.child.childrens.splice(this.child.childrens.indexOf(obj),1);
        }
    }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Vue3 - Quasar q-tabs do not maintain values between them

I am facing an issue while designing a screen to submit a form in modal using vue3 and quasar. I have organized the form components by tabulating them, but when I switch tabs, the current selection disappears, showing the old value when I return. However, ...

"Learn how to convert basic input fields into user-friendly Bootstrap input groups using the power of jQuery

Is there a way to use jQuery to convert my basic input field into a bootstrap input-group like the one shown below? This is how I created the input: <div class='input-group date' id='ff'> <input type='text' class= ...

Importing Angular libraries with the * symbol

One of the key modules in my library is sha256. To import it, I had to use the following syntax: import sha256 from 'sha256'; However, while researching this issue, I came across a question on Stack Overflow titled: Errors when using MomentJS ...

What's causing me to encounter two canvases while implementing PIXI.js in my Next.js project?

I'm facing a challenge in my game development project that utilizes PIXI.js within a Next.js setup. Currently, I am experiencing an issue where the webpage is displaying two canvases instead of one, leading to unexpected rendering issues and impacting ...

Issue with nextElementSibling not applying CSS style

My current issue revolves around a button that is designed to open or close a collapsible div. The HTML structure of this element looks like the following: <div class='outer-collapsible'> <button type='button' class='col ...

Increase or decrease the quantity of items by cloning with Jquery and dynamically changing the ID

Currently, I am working on a jQuery clone project where I need to dynamically add and delete rows. Despite searching extensively on Stack Overflow and Google, I only have a basic understanding of how jQuery clone works. Any suggestions would be greatly ap ...

I'm curious about something I noticed in an HTML example within the text content section of elements. Can you help clarify this for me?

I recently came across a repository that was part of a bootcamp curriculum for learning full stack development. In one of the lessons on jQuery, students were tasked with building a calculator. However, I noticed some strange variables in the HTML where te ...

transferring a JavaScript variable to PHP upon submitting a form

This question arises after my previous inquiry on the topic of counting the rows in an HTML table using PHP. Since I didn't find a solution that worked for me, I am exploring new methods but struggling with the implementation. My approach involves ass ...

Creating paths for a subdirectory in Vue 3

I am currently utilizing a Vue Starter Template: Vite + Vue 3 + Tailwind CSS (starter) ⚡ Tailwind CSS v3.0.0-alpha ⚠ Vue Router 4.x My goal is to have the application run in a subdirectory format like: domain.com/VueApp. To achieve this, I referred t ...

What is the process for sending JavaScript with an Ajax request?

Working with ajax and javascript for the first time, I'm no expert in web development. Here is the code I've written and tested so far. I have a select div containing some options. <select id="month" onchange="refreshGraph()"> When an op ...

Troubleshooting Problems with Fancybox Scaling on Small Landscape-Oriented Mobile Devices

Issue Description: In my responsive web design, I am utilizing Fancybox v2.1.5. The problem arises when smaller mobile devices with a more rectangular shape than square are used. In portrait orientation, when invoking Fancybox, it expands to the width of ...

Ways to determine if content is visible within a div

My website contains a script that brings in content from an ad network and displays it within a div element. Unfortunately, this particular ad network only fills ads 80% of the time, leaving the remaining 20% of the time without any ads to display. This la ...

Refreshing a webpage to accurately display changes made in a CRUD application without the need for a hard reset

My to-do app is almost fully functional - I can create items, mark them as completed, and delete them using a delete button. However, there's one issue: when I delete an item, the page doesn't update in real-time. I have to manually refresh the p ...

Mongoose encountered an error when attempting to cast the value "......" as an ObjectId in the "author" path. The error was caused by a BSONError

I'm currently facing an issue with Mongoose in my NextJS project. Specifically, I am encountering a problem when trying to save a document where one of the fields references an ObjectId. The error message I receive is as follows: Cast to ObjectId fail ...

Issue with Stack Divider not appearing on Chakra UI card

I'm currently designing a card element using Chakra UI. However, I've noticed that the Stack Divider in the Card Body isn't displaying as expected. Is there a specific way it needs to be structured for it to show up? For example, should I se ...

Managing a collection of input values

Is there a way to effectively manage an array of input fields using reactjs? Take for instance this text field: <input type="text" value="" name="test[]" /> Below is the code I'm currently working with: render () { ...

The $digest function in Angular's $rootScope

While engrossed in the incredible book, Mastering Web Development in AngularJS, I stumbled upon this code snippet: var Restaurant = function ($q, $rootScope) { var currentOrder; this.takeOrder = function (orderedItems) { currentOrder = { deferred ...

Sending an array as JSON data to PHP using the $.ajax post method. The $_POST array is

After spending a considerable amount of time on this, I'm still struggling to figure out what I'm doing wrong. I'm having difficulty retrieving the data in the PHP file. I've made multiple calls to "copy" to populate the "result" arr ...

Encountered an invalid prop type error while employing CSSTransition

Encountering an issue with the implementation of CSSTranstion for React. The purpose is to animate the mobile menu in a small application. Everything was functioning properly until the inclusion of the react-transition-group package, specifically using < ...

Conceal elements within a div using the 'elementFromPoint' function

In my HTML, I have a div that contains an icon and some text. I want to make it so that when I hover over the div with my mouse, only the div itself is visible to the 'elementFromPoint' function. How can I achieve this? Here is an example of th ...