Vue.js Как сделать перетаскивание drag and drop содержимого таблицы
Пытаюсь сделать таблицу на vue.js, в которой можно drag&drop перетаскивать содержимое из ячейки в ячейку.
<div class="grid">
<div
draggable="true"
v-for="slot of slots"
:key="slot.index"
:data-index="slot.index"
@dragstart="drag"
@dragover.prevent
@drop.stop="drop"
>
<span v-if="slot.content">
{{ slot.content }}
</span>
</div>
</div>
</template>
<script>
export default {
name: "Storage",
props: ['id', 'items' ],
data() {
return {
cells: 27,
currentTarget: '',
slots: [],
};
},
mounted() {
for (let i = 0; i < this.cells; i++) {
this.slots.push({content: null, index: i})
}
for (let item of this.items) {
this.slots[item.y * 3 + item.x].content = item
}
},
methods: {
dragStart(item) {
this.draggedSlot = item;
},
dragEnd() {
this.draggedSlot = null;
},
allowDrop(event, slot) {
event.preventDefault();
return true;
},
drag (cell) {
console.log(cell.target.dataset.index)
this.currentTarget = cell.target.dataset.index
},
drop (cell) {
if (cell.target.dataset.index === undefined) {
const parentDiv = cell.target.parentNode
console.log(parentDiv.dataset.index)
const oldVal = this.slots[this.currentTarget].content
const newVal = this.slots[parentDiv.dataset.index].content
this.slots[parentDiv.dataset.index].content = oldVal
this.slots[this.currentTarget].content = newVal
} else {
console.log(cell.target.dataset.index)
const oldVal = this.slots[this.currentTarget].content
const newVal = this.slots[cell.target.dataset.index].content
this.slots[cell.target.dataset.index].content = oldVal
this.slots[this.currentTarget].content = newVal
}
}
}
}
</script>
<style scoped>
table {
width: auto;
}
.grid {
display: grid;
grid-template-rows: 1fr 1fr 1fr;
grid-template-columns: 1fr 1fr 1fr;
grid-gap: 0.2vw;
}
.grid > div {
font-size: 5vw;
padding: .8em;
background: rgb(80, 80, 80);
text-align: center;
}
</style>
Есть готовая таблица, которая реализует перетаскивание. Console.log показывает, из какой ячейки берем и в какую ячейку кладем Имеется цикл, который рассчитывает положение содержимого, как я понял.Все работает.
for (let item of this.items) {
this.slots[item.y * 3 + item.x].content = item
}
А как в ячейку закинуть content, какой-нибудь item в пустую ячейку, когда расположение и координаты в ячейке заданы через position_x и position_y, если items представляет собой следующее:
items=[
{id:1, position_x: -1, position_y: -1},
{id:2, position_x: 3, position_y: 2}
]
Ответы (1 шт):
Автор решения: Evgenii Kantemirov
→ Ссылка
Решение, которое работает для одного объекта.
<div>
<table>
<tr v-for="(row, i) in table">
<td draggable="true"
:key="j"
:data-row="i"
:data-ceil="i"
@drag.start="drag"
@dragover.prevent
@drop.stop="drop"
v-for="(item, j) in row">
<div class='item' v-if="item">
<div class='id'>{{item.id}}</div><br>{{item.name}}
</div>
</td>
</tr>
</table>
</div>
</template>
<script>
import _ from "lodash";
export default {
name: "Storage",
props: [],
data() {
return {
size: [8, 8],
displayed: false,
currentTarget: [],
nextTarget: [],
currentPosItem: {},
items: [
{
id: 4,
name: "Queen",
quantity: 4,
position_x: 3,
position_y: 2,
},
{
id: 3,
name: "Queen",
quantity: 1,
position_x: 0,
position_y: 0,
}
]
}
},
computed: {
table: function () {
const map = [];
for (let x = 0; x < this.size[0]; x++) {
map.push(_.fill(Array(this.size[1]), null));
}
_.forEach(this.items, (item) => {
if (item.position_x !== -1 && item.position_y !== -1)
map[item.position_x][item.position_y] = item;
this.currentPosItem = item;
if (item.position_x !== -1 && item.position_y !== -1)
map[item.position_x][item.position_y] = this.currentPosItem;
});
return map;
},
},
methods: {
drag(event) {
let target = event.target
let i = target.dataset.row;
let j = target.dataset.ceil;
this.currentTarget = [j, i];
//if (cell.tagName != 'SPAN') return;
let td = target.textContext;
console.log(td)
},
drop(event) {
let target = event.target
// console.log(cell);
let m = target.parentNode.rowIndex;
let n = target.cellIndex;
this.nextTarget = [m, n];
this.currentPosItem.position_x = m;
this.currentPosItem.position_y = n;
console.log(this.currentPosItem);
}
},
};
</script>
<style scoped>
table {
width: auto;
}
td {
width: 40px;
height: 40px;
border: 1px solid #000;
}
.id{
background-color: yellow;
}
</style>