chart.jsvuejs3gridstack

How to remove single component from object in gridstack Vue3


I am trying to remove a single component from an object in gridstack.js using index and keys. Components are created by v-for directive.

I already have the index and key but components.splice(index,1) and grid.removeWidget(key, false); functions don't achieve this as shown in the documentation. What I am i doing wrong.

Thanks

<template>
    <div class="right">
        <button class="ds" @click="addNewWidget()">Add Widget</button>
         //works okay
        <button class="ds" @click="deleteWidget()">Clear</button>
    </div>

    <section class="grid-stack">
        <div v-for="(component, key, index) in components" :key="'component' + index" :gs-id="key"
            class="grid-stack-item" :gs-x="component.gridPos.x" :gs-y="component.gridPos.y" :gs-h="component.gridPos.h"
            :gs-w="component.gridPos.w" gs-auto-position="true">
            <div class="grid-stack-item-content">
                <component :is="component.name" v-bind="component.props" />
              //Uncaught TypeError: Cannot read properties of undefined (reading 'splice')
                <button @click="remove(index, key, component)">remove</button>
            </div>
        </div>
    </section>
</template>
  
<script>
import { ref, onMounted, reactive, nextTick } from 'vue';
import "gridstack/dist/h5/gridstack-dd-native";
import 'gridstack/dist/gridstack.min.css';
import { GridStack } from 'gridstack';
import BarChart from './BarChart.vue';
import PieChart from './PieChart.vue';
import LineChart from './LineChart.vue';
import Widget from './HalfDoughnut.vue';

export default {
    name: "Dashboard",
    setup() {
        let info = ref("");
        let grid = null;

        let components = reactive({
            yourRandomComponent1: {
                name: "BarChart", props: {}, gridPos: { x: 0, y: 1, w: 6, h: 7 }
            },
            yourRandomComponent2: {
                name: "PieChart", props: {}, gridPos: { x: 0, y: 1, w: 6, h: 7 }
            },
        });

        onMounted(() => {
            grid = GridStack.init({
                float: true,
                cellHeight: "70px",
                minRow: 1,
            });

            grid.on("dragstop", (event, element) => {
                console.log("move event!", event, element);
                const node = element.gridstackNode;
                info.value = `you just dragged node #${node.id} to ${node.x},${node.y} – good job!`;
            });
        });

        // this will of course only work once because of the object-key
        function addNewWidget() {
            components.yourRandomComponent3 = {
                name: "Widget", props: {}, gridPos: { x: 0, y: 1, w: 6, h: 7 }
            };

            // we have to wait for vue to update v-for, 
            // until then the querySelector wont find the element
            nextTick(() => {
                console.log(grid);
                let compEl = document.querySelector('[gs-id="yourRandomComponent3"]');
                console.log(compEl);
                grid.makeWidget(compEl);
            });
            console.warn("i will only work once, fix my inputs to reuse me");
        }
        function remove(index, key) {
            console.log(key)
            //Uncaught TypeError: Cannot read properties of undefined (reading 'splice')
            components.splice(index, 1);
            grid.removeWidget(key, false);

        }
        function deleteWidget(){
            grid.removeAll(true);
        }

        return {
            info,
            components,
            addNewWidget,
            deleteWidget,
            remove
        };
    },
    components: {
        // eslint-disable-next-line vue/no-unused-components
        BarChart, PieChart, LineChart, Widget
    }
}
</script>
  


Solution

  • you are declaring components as a reactive which means you don't need to use .value use delete componennts[key] but a regular object

    also use const to declare ref, reactive... to avoid errors