Search code examples
javascriptvue.jsvuedraggable

How do I use Vue-draggable and Vuex to dynamically split up one list into multiple lists?


I have an array that takes input from the user from answering multiple questions. These values are stored in my vuex store and the results are displayed on screen in a draggable list.

computed: {
  allValues() {
        const val1 = this.responses1
        const val2 = this.responses2
        const val3 = this.responses3
        const val4 = this.responses4
        const val5 = this.responses5
        const val6 = this.responses6
        const val7 = this.responses7
        const coreValues = val1.concat(val2,val3,val4,val5,val6,val7)
        this.$store.dispatch('corevalues/loadCoreValues', coreValues)
        return this.$store.getters['corevalues/getCoreValues']
    }
  }

Draggable List

 <draggable :v-model="allValues" 
    options:='group: "allValues"'>
     <transition-group>
      <div v-for="val in allValues" :key="val.value">
          {{val.value}}
      </div>
    </transition-group>
 </draggable>

{{ allValues }}

However, on screen although I can drag and sort the values - they do not reorder in the Vuex Store, only on-screen.

1) I need them to re-order in the store.

2) Although a single array is created through the user input I require users to be able to drag values into a second or even a third column in order to group them.

How do I make it so my on screen changes are reflected in the store - even in a new array - and so that my list can be split up into multiple columns?

This my my Code Sandbox: https://codesandbox.io/embed/vue-template-j53g3

EDIT: After Sabee response

I have implemented the following code:

watch:{
    allValues: {
        handler: function(newValue) {
          console.log('here', newValue)
          this.$store.dispatch("corevalues/loadCoreValues", newValue);
        }
    },
    deep: true // deep watching changes
  },

But as the image below shows - the arary {{ allValues }} is still in the same order even though it has been re-arranged on screen.

enter image description here

2nd edit

Updated code as advised.

Console is logging 'Drag Ended' but as the screenshot below shows the Core Values in the store has not updated - this is after 'reloading state' via dev tools.

enter image description here


Solution

  • You can use

    watch:{
     list: {
            handler: function(newValue) {
                // do your job 
    
               // this.$store.commit("updateList", value);
               // commit your changes to store 
      }
    
            },
            deep: true // deep watching changes
        }
    

    }

    for checking changes and re-orders, also good solution create a button for saving user changes to store.

    UPDATE So drag changes not wathed :( ... But there are events in vue-draggable @end enter image description here On drag end you can store sorted array in vuex store

     <draggable :v-model="allValues" @end="onEnd">
              <transition-group>
                <div v-for="val in allValues" :key="val.value">{{val.value}}</div>
              </transition-group>
            </draggable>
    

    And in methods

      methods: {
        onEnd(){
          console.log("Drag ended")
            this.$store.dispatch("corevalues/loadCoreValues", this.allValues);
        },
    

    Finally

    <script>
    import draggable from "vuedraggable";
    export default {
      components: {
        draggable
      },
      data() {
        return {
          num: 1,
          allValues:[],
          responses1: [],
          responses2: [],
          responses3: [],
          responses4: [],
          responses5: [],
          responses6: [],
          responses7: [],
          question: [
            {
              id: 1,
              question: "What do you believe defines the culture at your company?"
            },
            {
              id: 2,
              question:
                "What values do you bring to your work that you consistently uphold whether or not they are rewarded?"
            },
            {
              id: 3,
              question:
                "What do you truly stand for in your work? What do you believe your company truly stands for?"
            },
            {
              id: 4,
              question:
                "What do your customers believe about you? What do they believe you stand for?"
            },
            {
              id: 5,
              question:
                "What values does your company consistently adhere to in the face of obstacles?"
            },
            {
              id: 6,
              question: "What are your company’s greatest strengths?"
            },
            {
              id: 7,
              question:
                "What are the top three to five most important behaviours you should expect from every employee (including you)?"
            }
          ]
        };
      },
      computed: {
        number(number) {
          return this.number + number;
        },
        // allValues: {
        //   // get() {
        //   //   const val1 = this.responses1;
        //   //   const val2 = this.responses2;
        //   //   const val3 = this.responses3;
        //   //   const val4 = this.responses4;
        //   //   const val5 = this.responses5;
        //   //   const val6 = this.responses6;
        //   //   const val7 = this.responses7;
        //   //   const coreValues = val1.concat(val2, val3, val4, val5, val6, val7);
        //   //   // this.$store.dispatch("corevalues/loadCoreValues", coreValues);
        //   //   // return this.$store.getters["corevalues/getCoreValues"];
        //   //   return coreValues;
        //   // },
        // }
      },
      watch: {
        responses1: {
          handler: function(newValue) {
            console.log(newValue)
            this.appendWithoutDublicates(this.responses1)
          },
          deep: true // deep watching changes if you need
        },
        // responses from 2 to 7: { 
        //   handler: function(newValue) {
        //     console.log(newValue)
        //     this.appendWithoutDublicates(this.responses1)
        //   },
        //   deep: true // deep watching changes if you need
        // },
        allValues: {
          handler: function(newValue) {
            console.log(newValue)
           this.$store.dispatch("corevalues/loadCoreValues", newValue);
          },
          deep: true // deep watching changes if you need
        },
    
      },
      methods: {
        appendWithoutDublicates(values){
          this.allValues = this.allValues.concat(values.filter(item => {
                return this.allValues.findIndex(obj => obj.value === item.value) < 0;
             }));
        },
        onEnd() {
          console.log("Drag ended");
          console.log(this.allValues);
          this.$store.dispatch("corevalues/loadCoreValues", this.allValues);
        },
        setValues() {
          // this.allValues = coreValues
        },
        questionNumber(num) {
          this.num += num;
        },
        addresponse1: function() {
          var elem = document.createElement("tr");
          this.responses1.push({
            value: ""
          });
        },
        removeElement1: function(index) {
          this.responses1.splice(index, 1);
        },
        addresponse2: function() {
          var elem = document.createElement("tr");
          this.responses2.push({
            value: ""
          });
        },
        removeElement2: function(index) {
          this.responses2.splice(index, 1);
        },
        addresponse3: function() {
          var elem = document.createElement("tr");
          this.responses3.push({
            value: ""
          });
        },
        removeElement3: function(index) {
          this.responses3.splice(index, 1);
        },
        addresponse4: function() {
          var elem = document.createElement("tr");
          this.responses4.push({
            value: ""
          });
        },
        removeElement4: function(index) {
          this.responses4.splice(index, 1);
        },
        addresponse5: function() {
          var elem = document.createElement("tr");
          this.responses5.push({
            value: ""
          });
        },
        removeElement5: function(index) {
          this.responses5.splice(index, 1);
        },
        addresponse6: function() {
          var elem = document.createElement("tr");
          this.responses6.push({
            value: ""
          });
        },
        removeElement6: function(index) {
          this.responses6.splice(index, 1);
        },
        addresponse7: function() {
          var elem = document.createElement("tr");
          this.responses7.push({
            value: ""
          });
        },
        removeElement7: function(index) {
          this.responses7.splice(index, 1);
        }
      }
    };
    </script>
    

    And update draggable also

    <draggable :list="allValues" @end="onEnd">
      <transition-group>
        <div v-for="val in allValues" :key="val.value">{{val.value}}</div>
      </transition-group>
    </draggable>