I use Vue.js and Dragula to create a drag and drop page. Each tile contains its own dataset, so each tile is a Vue component.
The problem is that as soon as I drag one of the fragments, the DOM elements and the data array in the Vue instance fall out of sync and start causing problems. Just dragging and dropping does not create a problem, but as soon as I drag and drop something and then try to delete it, everything goes wrong.
Here's the script: https://jsfiddle.net/wfjawvnL/13/
Here is 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 is 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 call Dragula as follows:
dragula([document.getElementById('draggable')]).on('drop', function (el, target, source, sibling) { vm.reorder(el, sibling); });
This fiddle works fine, but does not use components: https://jsfiddle.net/z2s83yfL/1/