[Vuejs]-How to add and remove items between select box in vue js?

5πŸ‘

βœ…

If you actually want to move items between arrays, you can do it this way. I cleaned code a bit to concentrate only on this.

Html:

<script src="https://unpkg.com/vue@2.2.6/dist/vue.js"></script>

<div id="app">
  <select v-model="availableFacilitiesSelectedValues" multiple="multiple">
    <option v-for="facility in availableFacilities" v-bind:value="facility.value">{{facility.text}}</option>
  </select>
  <select v-model="selectedFacilitiesSelectedValues" multiple="multiple">
    <option v-for="facility in selectedFacilities" v-bind:value="facility.value">{{facility.text}}</option>
  </select>
  <br/>
  <a @click.prevent="addFacilities" href="#">add</a>
  <br/>
  <a @click.prevent="removeFacilities" href="#">remove</a>
</div>

JS:

new Vue({
  el: "#app",
  data: {
    availableFacilities: [{
      value: 1,
      text: 'Double (Non a/c)',
    }, {
      value: 2,
      text: 'Premium Double (a/c)',
    }, {
      value: 3,
      text: 'Standard Double (a/c)',
    }, ],
    selectedFacilities: [],
    availableFacilitiesSelectedValues: [], // Facility values, selected in first control
    selectedFacilitiesSelectedValues: [], // Facility values, selected in second control
  },
  methods: {
    move(value, arrFrom, arrTo) { // Helper function to transfer facility from one array to another by 'value' property
        var index = arrFrom.findIndex(function(el) {
          return el.value == value;
        });
        var item = arrFrom[index];

        arrFrom.splice(index, 1);
        arrTo.push(item);
      },
      addFacilities() {
        var selected = this.availableFacilitiesSelectedValues.slice(0);

        for (var i = 0; i < selected.length; ++i) {
          this.move(selected[i], this.availableFacilities, this.selectedFacilities);
        }
      },
      removeFacilities() {
        var selected = this.selectedFacilitiesSelectedValues.slice(0);

        for (var i = 0; i < selected.length; ++i) {
          this.move(selected[i], this.selectedFacilities, this.availableFacilities);
        }
      },
  }
})

Working fiddle example: https://jsfiddle.net/9x0s73gk/

1πŸ‘

How about

export default {
  data(){
    return{
      facilitySelected:[],
      availableFacilities: [{
        value: 1,
        label: 'Double (Non a/c)',
        selected: false,
      },
      {
        value: 2,
        label: 'Premium Double (a/c)'
        selected: false,
      },
      {
        value: 3,
        label: 'Standard Double (a/c)'
        selected: false,
      }
    ],
  },
  computed: {
    selectedFacilities() {
      return this.availableFacilities.filter(f => f.selected);
    },
    unselectedFacilities() {
      return this.availableFacilities.filter(f => !f.selected);
    },
  }
},

And bind your <select>s to 2 computed list accordingly. When add/remove is clicked you just set the selected property of the items to true/false.

By the way, what you’re trying to implement looks very much like a transfer component. For example: http://element.eleme.io/#/en-US/component/transfer.

πŸ‘€Can Nguyen

1πŸ‘

I changed some parts in your code and then it worked.
I think the reason why it didn’t work is related to v-bind:value="facility.value", you bound object in first select box but integer value in second one. It made values bound by each v-model differed in types.
fiddle

new Vue({
  el: "#app",
  data: {
    facilitySelected1: [],
    facilitySelected2: [],
    availableFacilities: [{
        value: 1,
        text: 'Double (Non a/c)'
      },
      {
        value: 2,
        text: 'Premium Double (a/c)'
      },
      {
        value: 3,
        text: 'Standard Double (a/c)'
      }
    ],
    selectedFacilities: [],
  },
  methods: {
    removeFacilities() {
      this.selectedFacilities = this.selectedFacilities.filter(fac => !this.facilitySelected2.includes(fac));
      this.availableFacilities = [...this.availableFacilities, ...this.facilitySelected2];
      this.facilitySelected2 = [];
    },
    addFacilities() {
      this.availableFacilities = this.availableFacilities.filter(fac => !this.facilitySelected1.includes(fac));
      this.selectedFacilities = [...this.selectedFacilities, ...this.facilitySelected1];
      this.facilitySelected1 = [];
    }
  }
})
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://unpkg.com/vue@2.2.6/dist/vue.js"></script>
<div id="app">
  <select v-model="facilitySelected1" multiple="multiple" id="facilities" size="4" class="form-control">
  <option v-for="availability in availableFacilities" :value="availability">{{availability.text}}</option>
</select>

<a @click="removeFacilities" class="btn btn-default remove_option" rel="facilities2" id="remove"><i class="fa fa-arrow-left"></i></a>
<a @click="addFacilities" class="btn btn-default add_option" rel="facilities2" id="add"><i class="fa fa-arrow-right"></i></a>
<select  v-model="facilitySelected2" multiple="multiple" id="facilities2" size="4" class="form-control">
  <option v-for="facility in selectedFacilities" :value="facility">{{facility.text}}</option>
</select>
</div>
πŸ‘€choasia

1πŸ‘

Check this solution I made:

https://jsfiddle.net/Lfd6j90c/2/

I’ve changed some of your code

        new Vue({
          el: "#app",
          data: {
            add: [],
            remove: [],
            facilitySelected: [],
            availableFacilities: [{
              value: 1,
              text: 'Double (Non a/c)'
            }, {
              value: 2,
              text: 'Premium Double (a/c)'
            }, {
              value: 3,
              text: 'Standard Double (a/c)'
            }]
          },
    
    
          methods: {
    
    
            addFacilities() {
                var af = this.availableFacilities;
                var fs = this.facilitySelected;
                this.add.forEach(function(element) {
            			fs.push(af[element]);
            			af.splice(element, 1);
                });
                this.availableFacilities = af;
                this.facilitySelected = fs;
              },
    
            removeFacilities() {
                var af = this.availableFacilities;
                var fs = this.facilitySelected;
                this.remove.forEach(function(element) {
            			af.push(fs[element]);
            			fs.splice(element, 1);
                });
                this.availableFacilities = af;
                this.facilitySelected = fs;
              }
    
          }
        })
        <script src="https://unpkg.com/vue@2.2.6/dist/vue.js"></script>
        <div id="app">
          <div class="row">
            <div class="col-xs-5">
              <select v-model="add" multiple="multiple" size="4" class="form-control">
                <option v-for="(item, index) in availableFacilities" v-bind:value="index">
                  {{ item.text }}
                </option>
              </select>
            </div>
            <div class="col-xs-2 ">
              <button @click="removeFacilities" class="btn btn-default remove_option" rel="facilities2" id="remove"><</button>
              <button @click="addFacilities" class="btn btn-default add_option" rel="facilities2" id="add">></button>
            </div>
            <div class="col-xs-5">
              <select v-model="remove" multiple="multiple" size="4" class="form-control">
                <option v-for="(item, index) in facilitySelected" v-bind:value="index">
                  {{ item.text }}
                </option>
              </select>
            </div>
    
          </div>
    
        </div>

Leave a comment