1
votes

I have this html:

<div
class="data__file"
v-for="(data, index) in paginatedData"
:key="index"
>
 <label class="data__info" :for="data.idfile" @click="onClickWithShift($event, index)">
   <img
     :src="data.link"
     alt=""
     :class= "{ 'data__image' : 1 ,'data__image-active' : (data.checked === 1) }"
    />
    <input
     v-if="isManager === true"
     type="checkbox"
     class="data__access"
     :value="data.idaccess"
     :checked="(data.checked === 1) ? 1 : null"
     v-model="checkedFilesPermission"      
    />
          
    <input
     v-if="isManager === false"
     type="checkbox"
     class="data__access"
     :value="data.idfile"
     :checked="(data.checked === 1) ? 1 : null"
     v-model="checkedFilesDownload"       
    />
    </label>
</div>

This code generate list of checkbox inputs, then I need when user click on label with shift (because input`s is display:none), all checkboxes between clicked inputs will checked or unchecked like it make with jquery here How can I shift-select multiple checkboxes like GMail?

But I cant realise how I can get it.

Big thanks to user Spiky Chathu, I did how He said, and its work without v-model , but when I try use v-model, it doesn`t work.

also this is my data:

data() {
    return {
      isManager: this.$store.getters.isManager,
      checkedFilesPermission: [],
      checkedFilesDownload: [],
      lastCheckedIdx: -1,
      checkedCount: 0,  
      paginatedData: [
        {"link":"images/2020/08/20200803.jpg","idfile":296,"idaccess":2},
        {"link":"images/2020/08/20200807.jpg","idfile":6,"idaccess":99},
        {"link":"images/2020/08/20200812.jpg","idfile":26,"idaccess":29},
        {"link":"images/2020/08/202123.jpg","idfile":960,"idaccess":2919},
        {"link":"images/2020/08/2020032.jpg","idfile":16,"idaccess":9339},
        {"link":"images/2020/08/20200000.jpg","idfile":2,"idaccess":9},
      ]
    };

I think main problem that VUE somehow block input with v-model

2

2 Answers

0
votes

I have come up with a solution to your problem. I have added a mock object to recreate the same scenario hoping that you have a array of objects.


Editted : Solution has been modified to cater multiple deselect scenario


new Vue({
  el: '#app',
  data: {
    paginatedData: [
      {"link":"https://img.icons8.com/list","idfile":296,"idaccess":2},
      {"link":"https://img.icons8.com/list","idfile":6,"idaccess":99},
      {"link":"https://img.icons8.com/list","idfile":26,"idaccess":29},
      {"link":"https://img.icons8.com/list","idfile":960,"idaccess":2919},
      {"link":"https://img.icons8.com/list","idfile":16,"idaccess":9339},
      {"link":"https://img.icons8.com/list","idfile":2,"idaccess":9},
    ],
    lastCheckedIdx: -1,
    checkedFilesPermission : []
  },
  methods: {
    onClickWithShift(event, idx, idFile) {
  
      var action = (this.checkedFilesPermission.indexOf(idFile) === -1) ? 'select' : 'deselect';
      
      if (event.shiftKey && this.lastCheckedIdx !== -1) {
      
        var start = this.lastCheckedIdx;
        var end = idx-1;
        // can select top to bottom or bottom to top
        // always start with lesser value
        if (start > end) {
          start = idx+1;
          end = this.lastCheckedIdx;
        }
        
        for (var c = start; c <= end; c++) {
          var currentIdFile = this.paginatedData[c]['idfile'];
          this.markSelectDeselect(c, action, currentIdFile);
        }
      }
      
      this.markSelectDeselect(idx, action, idFile);
      this.lastCheckedIdx = idx;
      
      if (this.checkedFilesPermission.length === 0) {
        //reset last checked if nothing selected
        this.lastCheckedIdx = -1;
      }
    },

    markSelectDeselect(idx, action, idFile) {
      
      var currentPos = this.checkedFilesPermission.indexOf(idFile);
      
      if (action === 'select' && currentPos === -1) {
        this.checkedFilesPermission.push(idFile);
      } else if (action === 'deselect' && currentPos !== -1){
        this.checkedFilesPermission.splice(currentPos, 1);
      }
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
  <div
      class="data__file"
      v-for="(data, index) in paginatedData"
      :key="index"
  >
      <input
          :id="data.idfile"
          type="checkbox"
          class="data__access"
          :value="data.idfile"
          v-model="checkedFilesPermission"
      />
       <label class="data__info" :for="data.idfile" @click="onClickWithShift($event, index, data.idfile)">
          <img
              :src="data.link"
              alt=""
              :class= "{ 'data__image' : 1 ,'data__image-active' : (checkedFilesPermission.indexOf(data.idfile) !== -1) }"
          />
      </label>
  </div>
</div>

You need to click on the image icon to see the result, since you have mentioned the input is hidden. I kept it visible here so that you can see it is actually getting changed

0
votes

Here's something I just tried that seems to do the work

<template>
  <div>
    <div v-for="(item, index) in items" :key="index">
      <label>
        <input type="checkbox" v-model="item.checked" @click="checked($event, index)">
        {{item.file}}
      </label>
    </div>
    <pre>{{items}}</pre>

  </div>
</template>

<script>

export default {
  data() {
    return {
      lastCheckedIndex: null,
      lastChange: null,
      items: [
        { file: "foo1", idx: 10 },
        { file: "foo2", idx: 20 },
        { file: "foo3", idx: 40 },
        { file: "foo4", idx: 30 },
        { file: "foo5", idx: 10 },
        { file: "foo6", idx: 90 },
        { file: "foo8", idx: 50 },
      ]
    }
  },
  methods: {
    checked(event, index) {
      // wheter or not to the multiple selection
      if (event.shiftKey && (null != this.lastCheckedIndex) && (this.lastCheckedIndex != index)) {

        const dir = index > this.lastCheckedIndex ? 1 : -1; // going up or down ?
        const check = this.lastChange;                      // are we checking all or unchecking all ?

        for (let i = this.lastCheckedIndex; i != index; i += dir) {
          this.items[i].checked = check;
        }
      }

      // save action
      this.lastCheckedIndex = index; 
      this.lastChange = !this.items[index].checked; // onclick is triggered before the default change hence the !
    }
  },
};

</script>