Reda
Reda

Reputation: 711

Vuejs with JQuery UI sortable issue

I am trying to create a sortable list with a delete function using vuejs and jquery ui I have the following results

please check the following jsfiddle

https://jsfiddle.net/reda84/7ojgvwdw/

the delete function is working but once you start to sort the delete dose not work correctly anymore specially for the sorted item and items below it.

if I combine both component in one like the following fiddle it works fine but I don't want that because the original application is more complicated with more complex components and I would like to separate it.

https://jsfiddle.net/reda84/jv7zhz1u/

TLDR: here is the code

var listItem = Vue.extend({
   template: '<li class="ui-state-default">{{item.title}} {{item.id}} <span v-on:click="remove(item)"> x </span></li>',
   props: {
     item: Object
   },
   methods: {
     remove: function(item) {
       this.$dispatch('remove-item', item)
     }
   }
 });
 var sortableList = Vue.extend({
   template: '<ul id="sortable"><list-item v-for="item in list" :item="item" class="ui-state-default"></list-item></ul>',
   data: function() {
     return {
       list: [{ id: 1, title: "Item"},
                    { id: 2, title: "Item"},
              { id: 3, title: "Item"}]
     }
   },

   events: {
     "remove-item": function(item) {
       var index = this.list.indexOf(item)
       this.list.splice(index, 1);
     }
   },
   components: {
     listItem
   },
 });

 new Vue({
   el: 'body',
   ready: function() {
     $("#sortable").sortable();
     $("#sortable").disableSelection();
   },
   components: {
     sortableList
   },
 });

Upvotes: 2

Views: 2582

Answers (1)

asemahle
asemahle

Reputation: 20805

It looks like the v-for and sortable can't both be directly on a vue component. My guess is that Vue and JQuery conflict when they both try to manage the li elements.

It works if the component is a child of the v-for. Here is the updated fiddle, and a working code snippet:

Vue.component('list-item', {
  template: '#list-item',
  props: {
    item: Object
  },
  methods: {
    remove: function (item) {
      this.$emit('remove-item', item)
    }
  }
});

Vue.component('sortable-list', {
  template: '#sortable-list',
  data: function () {
    return {
      list: [{
        id: 1,
        title: "Item"
      }, {
        id: 2,
        title: "Item"
      }, {
        id: 3,
        title: "Item"
      }]
    }
  },
  methods: {
    "removeItem": function (item) {
      var index = this.list.indexOf(item)
      this.list.splice(index, 1);
    }
  }
});

new Vue({
  el: '#app',
  mounted: function () {
    $("#sortable").sortable();
    $("#sortable").disableSelection();
  }
});
#sortable {
  list-style-type: none;
  margin: 0;
  padding: 0;
  width: 60%;
}

#sortable li {
  font-family: Arial;
  margin: 0 3px 3px 3px;
  padding: 0.4em;
  padding-left: 1.5em;
  font-size: 1.4em;
  height: 18px;
}

#sortable li span {
  float: right;
  cursor: pointer
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.4/vue.js"></script>

<div id="app">
  <sortable-list></sortable-list>
</div>

<template id="list-item">
  <div class="ui-state-default">
    {{item.title}} {{item.id}} 
    <span v-on:click="remove(item)"> x </span>
  </div>
</template>

<template id="sortable-list">
  <ul id="sortable">
    <li v-for="item in list">
      <list-item :item="item" 
                 class="ui-state-default"
                 @remove-item="removeItem">
      </list-item>
    </li>
  </ul>
</template>


Note: the snippet has been updated to use Vue 2.0 syntax.

Upvotes: 2

Related Questions