How can I create an array of id's from the selected option in vue-multiselect plugin?

Viewed 122

I've created an Laravel Vue SPA app. Right now, I can successfully retrieved the data in object format and can display the names in vue-multiselect (https://vue-multiselect.js.org/) when selected. Also, I can already save the selected options to the database in an object format. My question is how can I save only the id's in an array?

This is the results from api:

[
  {
    "id": 1,
    "name": "Shoe Machine Operators",
    "description": "Iusto cupiditate quo veniam.",
    "created_at": "2022-03-23T10:23:35.000000Z",
    "updated_at": "2022-03-23T10:23:35.000000Z"
  },
  {
    "id": 2,
    "name": "Librarian",
    "description": "Vero eius quidem quo fugiat.",
    "created_at": "2022-03-23T10:23:35.000000Z",
    "updated_at": "2022-03-23T10:23:35.000000Z"
  }
]

Here's my markup code where my vue-multiselect element is:

<form @submit.prevent="addEmployee">
    <div class="flex space-x-6 md:w-3/4">
        <div class="md:w-3/6 mb-4 flex-1">
            <label class="block text-gray-700 text-sm font-bold mb-2" for="name">First Name</label>
            <input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline required" name="name" id="name" type="text" placeholder="First Name" tabindex="1" v-model="employee.first_name" />
        </div>
        <div class="md:w-3/6 mb-4 flex-1">
            <label class="block text-gray-700 text-sm font-bold mb-2" for="name">Last Name</label>
            <input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline required" name="name" id="name" type="text" placeholder="Last Name" tabindex="2" v-model="employee.last_name" />
        </div>
    </div>
    <div class="flex space-x-6 md:w-3/4">
        <div class="md:w-3/6 mb-4 flex-1">
            <label class="block text-gray-700 text-sm font-bold mb-2" for="designation_id">Designation</label>
            <multiselect v-model="employee.designation_id" 
                :options="designation_options" 
                :multiple="true" 
                :close-on-select="false" 
                :clear-on-select="false" 
                :preserve-search="true" 
                placeholder="Pick one or many" 
                label="name" 
                track-by="name" 
                :preselect-first="true"
                >
                <template slot="selection" slot-scope="{ values, search, isOpen }"><span class="multiselect__single" v-if="values.length &amp;&amp; !isOpen">{{ values.length }} options selected</span></template>
            </multiselect>
            <pre class="language-json"><code>{{ employee.designation_id }}</code></pre>
        </div>
        <div class="md:w-3/6 mb-4 flex-1">
            <label class="block text-gray-700 text-sm font-bold mb-2" for="position_id">Position</label>
            <multiselect v-model="employee.position_id" 
                :options="position_options" 
                :multiple="true" 
                :close-on-select="false" 
                :clear-on-select="false" 
                :preserve-search="true" 
                placeholder="Pick one or many" 
                label="name" 
                track-by="name" 
                :preselect-first="true"
                >
                <template slot="selection" slot-scope="{ values, search, isOpen }"><span class="multiselect__single" v-if="values.length &amp;&amp; !isOpen">{{ values.length }} options selected</span></template>
            </multiselect>
            <pre class="language-json"><code>{{ employee.position_id }}</code></pre>
        </div>
    </div>
    <div class="flex space-x-6 md:w-3/4">
        <div class="md:w-3/6 mb-4 flex-1">
            <label class="block text-gray-700 text-sm font-bold mb-2" for="basic_pay">Basic Pay</label>
            <div class="relative rounded">
                <div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
                    <span class="text-gray-700">₱</span>
                </div>
                <input class="shadow appearance-none border rounded w-full py-2 pl-8 pr-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline required" name="basic_pay" id="basic_pay" type="number" step="any"  placeholder="00.00" tabindex="5" v-model="employee.basic_pay" />
                <div class="absolute inset-y-0 right-0 flex items-center"><label for="basic_pay" class="sr-only">Basic Pay</label>
                </div>
            </div>
        </div>
        <div class="md:w-3/6 mb-4 flex-1">&nbsp;</div>
    </div>
    <button type="submit" class="sm:hidden md:flex bg-blue-500 hover:bg-blue-400 text-white font-bold py-2 px-4 border-b-4 border-blue-700 hover:border-blue-500 rounded outline-none focus:outline-none">Create</button>
</form>

Here's my script:

<script>
    export default {
        data() {
            return {
                employee: {},
                designation_id: [],
                designation_options: [],
            }
        },
        methods: {
            addEmployee() {
                this.axios.post('/api/employees', this.employee).then(response => (this.$router.push({
                    name: 'employees'
                }))).catch(err => console.log(err)).finally(() => this.loading = false)
            },
            getDesignationNames() {
                this.axios.get('/api/designation').then((res) => {
                    this.designation_options = res.data;
                }).catch(err => console.log(err))
            },
        },
        created: function() {
            this.getDesignationNames();
        },
    } 
</script>

Any help is much appreciated.

I tried getting only the id using .map() function but it caused the vue-multiselect to not show the names and return only the first clicked result in an id format.

getDesignationNames() {
    this.axios.get('/api/designation').then((res) => {
        this.designation_options = res.data.map((a) => {
            return a.id;
        });
    }).catch(err => console.log(err))
},
1 Answers

Use v-model. Define v-model binding as an array.

Check this example

<script setup>
import { ref } from 'vue'
const data = ref([{id:1,name:"first"},{id:2,name:"second"},{id:3,name:"third"},{id:4,name:"forth"},{id:5,name:"fifth"}])
const selected = ref(["2","4"])
</script>
<template>
  <select v-model="selected" multiple>
    <option v-for="item in data" :value="item.id">{{item.name}}</option>
  </select>
  <div>Selected: {{selected}}</div>
</template>
Related