Search code examples
vue.jsvue-cli-3vue-multiselect

Vue-MultiSelect: Using two multiselects at once and how to hide options based on what is shown in other


I am using a plugin called Vue-MultiSelect and showing it twice in my component. The first multiselect has a label of "Add New Contacts" and the second multiselect has a label of "Current Listed Contacts".

How can I hide the users for the "Add New Contacts" multiselect dropdown if they are already listed in the "Current Listed Contacts"?

Screenshot of problem:

enter image description here

I am using props to show the users for the "Current Listed contacts" multiselect. Here's the code for my Single file component where these multiselects reside (also demo link: CodeSandBox Code Editor) Note: click on POSTS --> EDIT (Acme Widget) to see the page where I am talking about

<template>
  <div>
    <label>Add New Contacts:</label>
    <multiselect
      id="add_new_contacts_input"
      v-model="NewContacts"
      :options="options"
      label="lastname"
      placeholder="Select or search for an existing contact"
      track-by="uid"
      :loading="isLoading"
      :custom-label="selectedNameLabel"
      aria-describedby="searchHelpBlock"
      selectLabel
      :multiple="true"
    >
      <template
        slot="singleLabel"
        slot-scope="props"
      >{{ props.option.lastname }}, {{props.option.firstname}}</template>
      <template slot="option" slot-scope="props">
        <strong>{{ props.option.lastname }}</strong>
        , {{ props.option.firstname }} &mdash;
        <small>{{ props.option.email }}</small>
      </template>
    </multiselect>
    <!-- <small id="searchHelpBlock" class="form-text text-muted"><font-awesome-icon icon="exclamation-circle" /> If customer does not exist, you will be prompted to add a new customer</small> -->
    <!-- <h3>New contacts to be added:</h3>
    <ul>
      <li v-for="value in values" :key="value.uid">{{value.lastname}}, {{value.firstname}}</li>
    </ul>-->
    <label>Current Listed Contacts</label>
    <multiselect
      id="current_listed_contacts_input"
      v-model="CurrentListedValues"
      placeholder="There are no current contacts"
      label="lastname"
      track-by="uid"
      :options="options"
      :multiple="true"
      :custom-label="selectedNameLabel"
      :loading="isLoading"
      selectLabel
    >
      <!-- formatting for the drop down list -->
      <template slot="option" slot-scope="props">
        <strong>{{ props.option.lastname }}</strong>
        , {{ props.option.firstname }} &mdash;
        <small>{{ props.option.email }}</small>
      </template>
    </multiselect>
  </div>
</template>

<script>
import Multiselect from "vue-multiselect";
// import ApiService from "@/apiService";
export default {
  components: { Multiselect },
  props: ["users", "contacts"],
  data() {
    return {
      NewContacts: [],
      CurrentListedValues: this.contacts,
      options: this.users,
      isLoading: true
    };
  },
  created() {
    this.isLoading = false;
  },
  methods: {
    selectedNameLabel(option) {
      return `${option.lastname}, ${option.firstname} -- ${option.email}`;
    }
  }
};
</script>

Solution

  • you can use computed to filter your list:

      computed: {
        addOptions() {
          let opt = this.users;
          this.CurrentListedValues.forEach(c => {
            opt = opt.filter(i => i.uid !== c.uid);
          });
          return opt;
        }
      }
    

    and in your select list change options to addOptions: :options="addOptions"