如何在PrimeVue中的DataTable组件中添加draggable

问题描述 投票:0回答:1
vue.js datatable vuejs3 primevue vuedraggable
1个回答
0
投票

这里我尝试在 Primevue TreeTable 插槽中使用自定义逻辑,因为没有重新排序的道具。

这是 stackBlitz link 相同的

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue TreeTable with Drag-and-Drop</title>
    <link rel="stylesheet" href="https://unpkg.com/primevue/resources/themes/saga-blue/theme.css">
    <link rel="stylesheet" href="https://unpkg.com/primevue/resources/primevue.min.css">
    <link rel="stylesheet" href="https://unpkg.com/primeicons/primeicons.css">
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    <script src="https://unpkg.com/primevue/umd/primevue.min.js"></script>
    <script src="https://unpkg.com/primevue/umd/treetable/treetable.min.js"></script>
    <script src="https://unpkg.com/primevue/umd/column/column.min.js"></script>
</head>
<body>
    <div id="app"></div>
    <script>
        const { ref, onMounted } = Vue;
        const TreeTable = PrimeVue.TreeTable;
        const Column = PrimeVue.Column;

        const App = {
            components: {
                TreeTable,
                Column
            },
            setup() {
                const nodes = ref([
                    {
                        key: '0',
                        data: { name: 'Applications', size: '100kb', type: 'Folder' },
                        children: [
                            {
                                key: '0-0',
                                data: { name: 'Vue', size: '25kb', type: 'Folder' },
                                children: [
                                    { key: '0-0-0', data: { name: 'vue.app', size: '10kb', type: 'Application' } },
                                    { key: '0-0-1', data: { name: 'native.app', size: '10kb', type: 'Application' } },
                                    { key: '0-0-2', data: { name: 'mobile.app', size: '5kb', type: 'Application' } }
                                ]
                            },
                            { key: '0-1', data: { name: 'editor.app', size: '25kb', type: 'Application' } },
                            { key: '0-2', data: { name: 'settings.app', size: '50kb', type: 'Application' } }
                        ]
                    },
                    {
                        key: '1',
                        data: { name: 'Cloud', size: '20kb', type: 'Folder' },
                        children: [
                            { key: '1-0', data: { name: 'backup-1.zip', size: '10kb', type: 'Zip' } },
                            { key: '1-1', data: { name: 'backup-2.zip', size: '10kb', type: 'Zip' } }
                        ]
                    },
                    {
                        key: '2',
                        data: { name: 'Desktop', size: '150kb', type: 'Folder' },
                        children: [
                            { key: '2-0', data: { name: 'note-meeting.txt', size: '50kb', type: 'Text' } },
                            { key: '2-1', data: { name: 'note-todo.txt', size: '100kb', type: 'Text' } }
                        ]
                    }
                ]);

                const columns = ref([
                    { field: 'name', header: 'Name', expander: true },
                    { field: 'size', header: 'Size' },
                    { field: 'type', header: 'Type' }
                ]);

                const draggedNode = ref(null);

                const onDragStart = (event, node) => {
                    draggedNode.value = node;
                    event.dataTransfer.effectAllowed = 'move';
                };

                const onDragOver = (event) => {
                    event.preventDefault();
                    event.dataTransfer.dropEffect = 'move';
                };

                const onDrop = (event, dropNode) => {
                    event.preventDefault();
                    if (draggedNode.value && draggedNode.value !== dropNode) {
                        // Find and remove the dragged node
                        const removeNode = (nodes, node) => {
                            for (let i = 0; i < nodes.length; i++) {
                                if (nodes[i] === node) {
                                    return nodes.splice(i, 1)[0];
                                }
                                if (nodes[i].children) {
                                    const result = removeNode(nodes[i].children, node);
                                    if (result) return result;
                                }
                            }
                        };
                        const dragged = removeNode(nodes.value, draggedNode.value);

                        // Find the drop node and insert the dragged node
                        const insertNode = (nodes, node, dragged) => {
                            for (let i = 0; i < nodes.length; i++) {
                                if (nodes[i] === node) {
                                    if (!nodes[i].children) nodes[i].children = [];
                                    nodes[i].children.push(dragged);
                                    return;
                                }
                                if (nodes[i].children) {
                                    insertNode(nodes[i].children, node, dragged);
                                }
                            }
                        };
                        insertNode(nodes.value, dropNode, dragged);
                    }
                    draggedNode.value = null;
                };

                return {
                    nodes,
                    columns,
                    onDragStart,
                    onDragOver,
                    onDrop
                };
            },
            template: `
                <div class="card">
                    <TreeTable :value="nodes" tableStyle="min-width: 50rem">
                        <Column v-for="col of columns" :key="col.field" :field="col.field" :header="col.header" :expander="col.expander">
                            <template #body="slotProps">
                                <div
                                    draggable="true"
                                    @dragstart="(event) => onDragStart(event, slotProps.node)"
                                    @dragover="onDragOver"
                                    @drop="(event) => onDrop(event, slotProps.node)"
                                >
                                    {{ slotProps.node.data[col.field] }}
                                </div>
                            </template>
                        </Column>
                    </TreeTable>
                </div>
            `
        };

        Vue.createApp(App).mount('#app');
    </script>
</body>
</html>

© www.soinside.com 2019 - 2024. All rights reserved.