vue.dragable.for

HTML

<script src="https://cdn.jsdelivr.net/sortable/1.4.2/Sortable.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.min.js"></script>
<script src="https://cdn.rawgit.com/David-Desmaisons/Vue.Draggable/master/dist/vuedraggable.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/2.3.1/vuex.js"></script>
<div id="main">
  {{gDocument}}
  <h1>Vue Dragable</h1>
  <div v-if="showDialog">
    <div>{{placeholder.type}}: </div>
    <span>{{placeholderText[placeholder.type]}}: </span>
    <input v-model="placeholder.value" />
    <button v-on:click="confirmAdd()">OK</button>
    <button v-on:click="cancelAdd()">Cancel</button>
  </div>

  <div class="drag">
    <draggable 
      id="list1" 
      class="dragArea" 
      :list="list1" 
      :move="checkMove"
      :options="{group:{name:'people', pull:'clone', put:false }}">
      <div 
        class="select-item"
        v-for="(element, index) in list1" >
        Add {{element.type}}
      </div>
    </draggable>                

    <draggable 
      id="list2" 
      class="dragArea" 
      :options="{group:'people'}" 
      @change="afterAdd"
      :list="gDocument">
      <div
        class="document-item"
        v-for="(element, index) in gDocument" 
        :key="index">
        <h3>{{element.type}}</h3>
        <img v-if="element.type==='image'" v-bind:src="element.value"/>
        <div>{{element.value}}</div>
      </div>
    </draggable>
  </div>

  <!-- <div class="normal">
    <h2>List 1 v-for</h2>
    <div>
      <div v-for="(element, index) in list1" :key="index">{{element.name}}</div>
    </div>
  
    <h2>List 2 v-for</h2>
    <div>
      <div v-for="(element, index) in list2" :key="index">{{element.name}}</div>
    </div>
  </div>
  
  <a href="index.html">See basic example</a>
  <a href="Two_Lists.html">See 2 lists example</a>
  <a href="Two_Lists.html">See 2 lists example</a> -->


</div>

CSS

.normal {
  background-color: grey;
}

.drag {
  display: flex;
  background-color: green;
}

.dragArea {
  border: solid 1px black;
  background-color: grey;
  min-height: 10px;
}



.document-item, .select-item {
  background-color: white;
  border: solid 1px black;
  margin: 8px 8px 8px 8px;
}

JavaScript

const { mapGetters } = Vuex

const store = new Vuex.Store({
  state: {
    itemTypes: [{ type:"table", id:1 }, {type:"image", id:2}, {type:"paragraph", id:3}],
    document: [{ type: 'paragraph', value: 'sampleText1' }, { type: 'image', value: 'http://via.placeholder.com/350x150' }, { type: 'paragraph', value: 'sampleText2' }]
  },
  getters: {
    gDocument: (state) => state.document
  },
  mutations: {
    APPEND_TO_DOCUMENT: (state, input) => {
    	state.document.splice(input.newIdx, 0, {
        type: input.type,
        value: input.value
      })
      state.document = state.document.filter((item) => item.value);
    },
    CANCEL_EDIT_DOCUMENT: (state) => {
    	state.document = state.document.filter((item) => item.value);
    }
  },
});

var vm = new Vue({
  el: "#main",
  store,
  data: {
  	list1: [{ type:"table", id:1 }, {type:"image", id:2}, {type:"paragraph", id:3}],
    showDialog: false,
    placeholderText: {
      table: 'Cell value',
      image: 'Link',
      paragraph: 'Text'
    },
    placeholder: {
      type: '',
      value: '',
      newIdx: 0
    }
  },
  computed: Object.assign({
  	// add computed properties here
    // exmaple: {
    //   get () { return 'example'},
    //   set (val) { this.$store.commit('sample', val) } 
    // }
  }, mapGetters([
    'gDocument'
  ])),
  methods:{
  	confirmAdd() {
    	this.$store.commit('APPEND_TO_DOCUMENT', this.placeholder)
      this.placeholder = {}
      this.showDialog = false
    },
    cancelAdd() {
    	this.$store.commit('CANCEL_EDIT_DOCUMENT')
    	this.placeholder = {}
      this.showDialog = false
    },
    afterAdd(evt) {
      this.placeholder = {
        type: evt.added.element.type,
        value: '',
        newIdx: evt.added.newIndex
      }
      this.showDialog = true
    },
    checkMove(evt) {
      this.futureIndex = evt.draggedContext.futureIndex;
      return true;
    }
  }
});