gridstack / gridstack.js

Build interactive dashboards in minutes.
https://gridstackjs.com
MIT License
6.3k stars 1.26k forks source link

GridStack's draggable option doesn't behave as expected when using Vue Rendering Grid Item Content #2685

Closed C0HERENCE closed 1 month ago

C0HERENCE commented 1 month ago

Subject of the issue

When attempting to utilize draggable, the expected behavior is not observed. Despite specifying draggable classes, the grid items remain draggable to any position, contrary to the intended restriction.

Your environment

"gridstack": "^10.1.2"

Steps to reproduce

See: https://jsfiddle.net/qasrj5ph I was combinig the following 2 demos Title drag Vue3: Gridstack Controls Vue Rendering Grid Item Content

Expected behavior

The draggable option, when provided with specific class names during initialization, should confine the drag-and-drop functionality of grid items to only those elements designated with the specified class.

adumesny commented 1 month ago

can you write a simple html demo ? I wuld rather not have to debug Vue example...

C0HERENCE commented 1 month ago

thanks for your response, I think vue.js is necessary to demonstrate the issue since the problem arises specifically when Gridstack is used with Vue.js for rendering content here I can provide a simplified demo

<html lang="en">
<head>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/gridstack@10.1.2/dist/gridstack.min.css">
    <script src="https://cdn.jsdelivr.net/npm/gridstack@10.1.2/dist/gridstack-all.js"></script>
    <style>
        .grid-stack { background: #FAFAD2; }
        .grid-stack-item-content { text-align: center; background-color: #18bc9c; }
        .card-header { cursor: move; min-height: 25px; background-color: #ccc }
        .card-header:hover { background-color: rgba(0, 0, 0, 0.5); }
        .content { text-align: center; }
    </style>
</head>

<body>
    <main id="app">
        <div class="grid-stack"></div>
    </main>
    <script type="module">
        import { createApp, onMounted, h, render } from "https://cdn.jsdelivr.net/npm/vue@3.0.11/dist/vue.esm-browser.js";

        const GridContentComponent = {
            template: `<div class="card-header">class="card-header"</div>
                     <div class="card-content">class="card-content"</div>`
        }

        createApp({
            setup() {
                let grid = null;
                onMounted(() => {
                    grid = GridStack.init({
                        draggable: {
                            handle: '.card-header'
                        }
                    });

                    grid.on('added', function (event, items) {
                        for (const item of items) {
                            const itemElContent = item.el.querySelector('.grid-stack-item-content')
                            const itemContentVNode = h(GridContentComponent)
                            render(itemContentVNode, itemElContent)
                        }
                    });
                    grid.load([{
                        h: 3,
                        w: 6
                    }]);
                });
            },
        }).mount("#app");

    </script>
</body>

</html>
adumesny commented 1 month ago

it's likely because it cannot find .card-header when creating the items, so the default to let entire widget drag. not sure of workaround if the div isn't there (or cannot be found using this api) in your case.

    // get the element that is actually supposed to be dragged by
    let handleName = option.handle.substring(1);
    this.dragEl = el.classList.contains(handleName) ? el : el.querySelector(option.handle) || el;
adumesny commented 1 month ago

you might be able to disable dragging and re-enable it after you have content there to be found.

don't forget to donate if you find this lib useful!