[Vuejs]-In vue2 v-for nested component props aren't updated after element is removed in parent

0👍

Please use Vue-devtools if you are not already using it. It shows the problem clearly, as seen in the image below:

Screenshot from Vue devtools

As you can see above, your day-list component comprises of all the days you have in the original list, with locations listed out directly. You need one more component in between, call it day-details, which will render the info for a particular day. You may have the location-list inside the day-details.

Here is the updated code which works:

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.3/vue.js"></script>

<div id="app">
    <day-list :days="days"></day-list>
</div>
Vue.component('day-list', {
    props: ['days'],
    template: `
        <div>
            <day-details :day="day" v-for="(day, index) in days">
                <a href="#" @click.prevent="remove(index)">Remove day</a>
            </day-details>
        </div>`,
    methods: {
        remove(index) {
            this.days.splice(index, 1);
        }
    }
});

Vue.component('day-details', {
    props: ['day'],
    template: `
        <div>
            {{ day.name }}
            <slot></slot>
            <location-list :locations="day.locations"></location-list>
            <br/>
        </div>`
});

Vue.component('location-list', {
    props: ['locations', 'services'],
    template: `
        <div>
            <div v-for="(location, index) in locations">
                {{ location.name }}
                <a href="#" @click.prevent="remove(index)">[x]</a>
            </div>
        </div>
    `,
    methods: {
        remove(index) {
            this.locations.splice(index, 1);
        }
    }
});

const app = window.app = new Vue({
    el: '#app',

    data: function() {
        return {
            days: [{
                name: 'Day 1',
                locations: [{
                    name: 'Berlin'
                }, {
                    name: 'London'
                }, {
                    name: 'New York'
                }]
            }, {
                name: 'Day 2',
                locations: [{
                    name: 'Moscow'
                }, {
                    name: 'Seul'
                }, {
                    name: 'Paris'
                }]
            }]
        }
    },

    methods: {}
});

One other thing – your template for location-list has an error – you are not closing the <a> element. You may use backtick operator to have multi-line templates as seen in the example above, to avoid template errors.

Also you are not supposed to change objects that are passed via props. It works here because you are passing objects which are passed by reference. But a string object getting modified in child component will result in this error:

[Vue warn]: Avoid mutating a prop directly…

If you ever get this error, you may use event mechanism as explained in the answer for this question: Delete a Vue child component

Leave a comment