Search code examples
vuejs2nuxt.jssortablejsvuedraggablevue.draggable

VueDraggable of Sortable is not working properly and send the choosed item to the first on init


I'm using Vue.Draggable in my Nuxt project. i used it in some pages and component and every thing is fine. but on one of my pages it gives me a silly problem!! when page is loaded, it send the chosen item to the first!! after that every thing works fine! even if i choose and unchoose without moving, things works fine!! i tried to check if the choosed went to first of array move it again properly. it worked when the chosen item is the first if array but if i choose others than first, on 2nd try it move another item too!! so i'm kinda stuck.

here is the code: btw there are some variables and methods that u cant find them like cmsListItems. they are globally added to my project

template:

<draggable v-model="myItemsArray" @end="onEnd" @choose="onChoose" @unchoose="onUnChoose" v-bind="getOptions()">
    <transition-group type="transition" name="sortable_transition">
      <categorylistcard v-for="(category, index) in cmsListItems" 
      listtype="cat"
      :key="category.id" 
      :cat="category" 
      :index="index" 
      :showforsub="showForSub"
      :parentarr="parentArr"
      @addnewsub="addNewCat()"
      :sub="true"
      :sublvl="true"
      :sortable="true"
      :btntitle="lang.addsubcat"
      />
    </transition-group>
  </draggable>

script:

export default {
    data(){
      return{
        oldIndex: '',
        newIndex: '',
        dragOptions: {
            ghostClass: "sortable_ghost",
            chosenClass: "sortable_chosen",
            handle: ".sortable_handle",
            disabled: false
        },
        isMoved: false,
        myItemsArray: [],
        originalItemsArray: [],
        choosedItem: null
      }
    },
    methods:{
          // ***** Reorder By Sorting *****\\

          this.isMoved = true
          this.oldIndex = event.oldIndex
          this.newIndex = event.newIndex
          console.log(this.myItemsArray[this.oldIndex])
          console.log(this.myItemsArray[this.newIndex])
          if(this.oldIndex !== this.newIndex){

            this.dragOptions.disabled = true
            let response = await this.axiosGet(`category/reorder/${this.originalItemsArray[this.oldIndex].id}/${this.originalItemsArray[this.newIndex].id}`)
            if(this.resOk(response.status)){
                this.noty(ALERT_TYPE[1], 'ok')
                this.originalItemsArray = this.myItemsArray
                this.isMoved = false
                this.dragOptions.disabled = false
                this.addClassToMovedItems(this.oldIndex)
                this.addClassToMovedItems(this.newIndex)
                this.setCmsListItems(this.myItemsArray)
                // this part is my defected solution
                setTimeout(() => {
                  if(this.myItemsArray[this.oldIndex].id === this.choosedItem.id || this.myItemsArray[0].id === this.choosedItem.id){
                    let arrayOfItems = [...this.originalItemsArray]
                    arrayOfItems.shift()
                    arrayOfItems.splice(this.newIndex,0,this.choosedItem)
                    this.setCmsListItems(arrayOfItems)
                    this.myItemsArray = [...this.cmsListItems]
                  }
                }, 50);
                // --------------------
            }else{
                this.isMoved = false
                this.myItemsArray = this.originalItemsArray
                this.dragOptions.disabled = false
                this.addClassToMovedItems(this.oldIndex)
                this.addClassToMovedItems(this.newIndex)
            }

          }else{
            this.isMoved = false
            this.myItemsArray = this.originalItemsArray
            this.dragOptions.disabled = false
            this.addClassToMovedItems(this.oldIndex)
            this.addClassToMovedItems(this.newIndex)
          }
          
      },
      addClassToMovedItems(index){
          if((index == this.oldIndex || index == this.newIndex) && this.isMoved == true){
              return 'sortable_moved'
          }else{
              return ''
          }
      }
    },
    async fetch(){
      this.btnLoading = true
      let response = await this.axiosGet(`categories/admin/0/1`)
      if(this.resOk(response.status)){
        if(this.notEmpty(response.data)){
          this.setCmsListItems(response.data.items)
          this.myItemsArray = [...this.cmsListItems]
          this.originalItemsArray = [...this.cmsListItems]
        }
        this.btnLoading = false
      }
    },
}

Solution

  • I kinda hacked through it, so i don't recommend it!!

    I got the chosen item with @choose and in my @end checked if first index of my array is the chosen item, unshift array and add the chosen to newIndex with splice() like bellow:

    setTimeout(() => {
      if(this.myItemsArray[this.oldIndex].id === this.choosedItem.id || this.myItemsArray[0].id === this.choosedItem.id){
        let arrayOfItems = [...this.originalItemsArray]
        arrayOfItems.shift()
        arrayOfItems.splice(this.newIndex,0,this.choosedItem)
        this.setCmsListItems(arrayOfItems)
        this.myItemsArray = [...this.cmsListItems]
        this.choosedItem = null
      }
    }, 1);