javascriptvue.jsvuejs3vue-componentvue-multiselect

Emit value from vue-multiselect.js component to main view


I want to pass data from my MultiSelectFilter component to my Home.vue view. When I use a console.log in the view I don't get any results. I looked at the documentation on using the @input event (https://vue-multiselect.js.org/#sub-events) to get all the changes to my selection but it doesn't work.

I'm new to vueJS and I don't understand my mistake.

I also tried to select all default values ​​but I cannot change the value on initialization.

My goal is to be able to loop in my view to have several multiple selectors, that's why I created a component.

My Home.vue

<template>
    <main id="Home-page">
        <h1>Dashboard</h1>
        <div class="filter-wrapper">
            <div class="filter-icon">
                <font-awesome-icon icon="fa-solid fa-filter" />
            </div>
            <div class="filter-content">
                <MultiSelectFilter :options="teamOptions" label="teams"/>
            </div>
        </div>
    </main>
</template>

<script>
import MultiSelectFilter from "@/components/MultiSelectFilter.vue";
import axios from 'axios';


export default {
    components: {
        MultiSelectFilter,
    },
    data() {
        return {
            teamOptions: [],
        };
    },
    methods: {
        updateSelectedOptions(value) {
            console.log(this.value = value)
        },
    },
    mounted() {
        axios
            .get("/api/teams")
            .then((response) => {
                const oReturn = []
                for (const [key, table] of Object.entries(response.data[0])) {
                    oReturn.push(Object.values(table).toString().toUpperCase())
                }
                this.teamOptions = oReturn;
            })
            .catch((error) => {
                console.error("Teams request error : ", error);
            });
    },
};
</script>

My MultiSelectFilter.vue

<template>
  <multiselect v-model="selectedOptions" :select-group-label="selectGroupLabel"
    group-values="data" group-label="all" :group-select="true" :options="transformedOptions" :placeholder="label"
    :multiple="true" :searchable="searchable" :close-on-select="false" @input="updateSelectedOptions">
    <template v-slot:noResult>{{ noResult }}</template>
  </multiselect>
</template>
<script>
import Multiselect from 'vue-multiselect';

export default {
  components: {
    Multiselect,
  },
  props: {
    options: Array,
    label: String,
  },
  data() {
    return {
      selectedOptions: [],
      noResult: "No result. Try again !",
      // value: [],
    };
  },
  computed: {
    transformedOptions() {
      return [{
        all: 'Tous',
        data: this.options,
      }];
    },
  },
  methods: {
    updateSelectedOptions(selectedOptions) {
      this.selectedOptions = selectedOptions;
      this.$emit('update:selectedOptions', selectedOptions);
    },
  }
};
</script>

Solution

  • You need to listen to the event in the parent component.

    Here is the documentation: https://vuejs.org/guide/components/events.html

    For this you can add @select="updateSelectedOptions"

    Home.vue

    <template>
        <main id="Home-page">
            <h1>Dashboard</h1>
            <div class="filter-wrapper">
                <div class="filter-icon">
                    <font-awesome-icon icon="fa-solid fa-filter" />
                </div>
                <div class="filter-content">
                    <MultiSelectFilter :options="teamOptions" label="teams" @select="updateSelectedOptions"/>
                </div>
            </div>
        </main>
    </template>
    

    MultiSelectFilter.vue

    methods: {
      updateSelectedOptions(selectedOptions) {
        this.selectedOptions = selectedOptions;
        this.$emit('select', selectedOptions);
      },
    }