Prasad Kavinda
Prasad Kavinda

Reputation: 188

Nested components not re-rendering properly: VueJs

I'm new to Vue and I'm building this forum kind of thing which can add nested comments in it. In here there are two components. PostForum and Comment. PostForum contains an input box and parent Comments. And inside each comment, I added child comments recursively.

When I adding comments, It works fine. But when deleting, it sends the ajax req but there's no re-rendering. So this is how I designed it. When deleting a comment, I emit a global event and in PostForum component I listen to that event and deleting that comment from its data. So isn't that supposed to re-render all the comments accordingly? Can anyone tell me what am I doing wrong here?

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>

Upvotes: 2

Views: 1371

Answers (1)

khofaai
khofaai

Reputation: 1357

I've tried this:

This code is just an example that may help you. In my case, child component is comment component in your case, and each child component has its own @action listener for his child component. So, he can use that to modify his own childrens.

Here is an example 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);
        }
    }
}

Upvotes: 2

Related Questions