I'm using Vue.js and Dragula to make a drag and drop tile page. Each tile contains its own set of data, so each tile is a Vue component.
The problem is that once I drag and drop one of the tiles, the DOM elements and the data array in the Vue instance fall out of sync and start to cause problems. Just dragging and dropping doesn't create a problem, but once I drag and drop something and then try to delete it, everything goes wrong.
Here's a fiddle: https://jsfiddle.net/wfjawvnL/13/
Here's my HTML, with the component template:
<body>
<div id="app">
<div id="draggable" class="wrapper">
<template v-for="(index, item) in list">
<block :id="index" :index="index" :item="item" :name="item.name">
</block>
</template>
</div>
<div class="footer">
<pre>{{ $data | json }}</pre>
</div>
</div>
</body>
<template id="block-template">
<div :id="index" :class="[name, 'block']">
<div class="text name">{{ name }}</div>
<div>Index: {{ index }}</div>
<span class="delete" v-on:click="removeItem(item)">✗</span>
</div>
</template>
Here's my Vue instance:
var vm = new Vue({
el: '#app',
data: {
list: [
{name: 'item1'},
{name: 'item2'},
{name: 'item3'},
{name: 'item4'},
{name: 'item5'}
]
},
methods: {
reorder: function (element, sibling) {
var children = element.parentNode.querySelectorAll(".block");
var length = this.list.length;
var ids = [];
for (var i = 0; i < length; i++) {
if (children[i].id) {
ids.push(children[i].id);
}
children[i].id = i;
}
var vm = this;
var newArr = ids.map(function (id) {
return vm.list[id];
});
this.list = newArr;
}
}
});
Here's the component:
Vue.component('block', {
template: '#block-template',
props: ['index', 'name', 'item'],
methods: {
removeItem: function (item) {
vm.list.$remove(item);
}
}
});
And I'm calling Dragula like this:
dragula([document.getElementById('draggable')]).on('drop', function (el, target, source, sibling) {
vm.reorder(el, sibling);
});
This fiddle works fine but doesn't use components: https://jsfiddle.net/z2s83yfL/1/