javascriptvue.jsvuejs2

Vue.js - Remove specific component dynamically


I am trying to dynamically create/remove a Vue component. I have figured out how to dynamically add the component, but I am having some troubles with allowing the users to remove the specific component.

Consider below two Vue files:

TableControls.vue

<a v-on:click="addColumn">Add Column</a>

<script>
    export default {
        methods: {
            addColumn: function () {
                Event.$emit('column-was-added')
            }
        }
    };

</script>

DocumentViewer.vue:

<div v-for="count in columns">
   <VueDragResize :id="count">
      <a @click="removeColumn(count)">Remove Column</a>
   </VueDragResize>
</div>

<script>
import VueDragResize from 'vue-drag-resize';

    export default {
        components: {
            VueDragResize
        },
        data() {
            return {
                columns: [1],
            }

        },
        created() {
            Event.$on("column-was-added", () => this.addColumn())
        },

        methods: {
            addColumn: function () {
                this.columns.push(this.columns.length + 1)
            },
            removeColumn: function (id) {
                this.columns.splice(id, 1)
            }
        }
    };
</script>

As you can see, whenever a user clicks on <a v-on:click="addColumn">Add Column</a>, it will submit an event, and the DocumentViewer.vue file will pick up it, firing the addColumn method. This will ultimately create a new <VueDragResize></VueDragResize> component.

This works great.

The problem is when I want to remove the component again. My removeColumn method simply removes an id from the columns array:

removeColumn: function (id) {
    this.columns.splice(id, 1)
}

This results in that a column is in fact removed. However, consider below example. When user clicks on the remove icon for the first column, it will remove the 2nd column instead. (And when there is only one column present, it cannot be removed).

Vue Example

I believe this is due to the fact that I splice() the array, but I cannot see how else I can remove the component dynamically?


Solution

  • I see, Array on Vue does not re render when you modify them.

    You need to use the

    Vue.set(items, indexOfItem, newValue)
    

    if you want to modify

    and use

    Vue.delete(target, indexOfObjectToDelete);
    

    If you want to delete an item from an array

    You may read the additional info here https://v2.vuejs.org/v2/api/#Vue-delete

    If you want to delete an item from array. Using this will cause the component to rerender.

    In this case it will be intuitive to do this

    removeColumn: function (id) {
       Vue.delete(this.columns, id)
    }
    

    Note that id should be the index. Vue.delete ensures the re-render of the component.

    EDIT, you must use the index, instead of the count here.

    <div v-for="(count, index) in columns">
       <VueDragResize :id="index">
          <a @click="removeColumn(index)">Remove Column</a>
       </VueDragResize>
    </div>