Skip to content
Snippets Groups Projects
Dropdown.vue 2.82 KiB
Newer Older
    :id="`custom-dropdown${identifier}`"
    :class="[
      'ui search selection dropdown',
      { 'active visible': isOpen },
      { disabled },
    ]"
    @click="toggleDropdown"
  >
    <input
      v-if="search"
Timothee P's avatar
Timothee P committed
      v-model="input"
      v-on:keyup.enter="select(0)"
      v-on:keyup.esc="toggleDropdown(false)"
Timothee P's avatar
Timothee P committed
      :placeholder="placehold"
      ref="input"
Timothee P's avatar
Timothee P committed
    <div v-if="!input" class="default text">{{ selected }}</div>
    <i class="dropdown icon"></i>
    <div :class="['menu', { 'visible transition': isOpen }]">
      <div
        v-for="(option, index) in processedOptions || ['No results found.']"
        @click="select(index)"
        :key="option + index"
        :class="[
          processedOptions ? 'item' : 'message',
          { 'active selected': option === selected },
        ]"
      >
        {{ option }}
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "Dropdown",

  props: ["options", "selected", "disabled", "search", "placeholder"],

  computed: {
    processedOptions: function () {
      //* si un objet {name, value}
Timothee P's avatar
Timothee P committed
        el.constructor === Object ? el.name : el
      );
      if (this.search && this.input !== "") {
        options = this.searchOptions(options);
      }
      return options.length > 0 ? options : null;
    },

    placehold() {
      return this.input ? "" : this.placeholder;
    },
      identifier: 0,
Timothee P's avatar
Timothee P committed
    toggleDropdown(val) {
      if (this.isOpen) {
        this.input = "";
      } else if (this.search) {
        //* put the focus on input if is a search dropdown
        this.$refs.input.focus({
          preventScroll: true,
        });
      }
      this.isOpen = val !== undefined ? val : !this.isOpen;
Timothee P's avatar
Timothee P committed

Timothee P's avatar
Timothee P committed
      // * toggle dropdown is called several time, timeout delay this function to be the last
Timothee P's avatar
Timothee P committed
        this.isOpen = false;
      }, 0);
      this.$emit("update:selection", this.options[index]);
      this.input = "";
    },
Timothee P's avatar
Timothee P committed

    searchOptions(options) {
      return options.filter((el) =>
        el.toLowerCase().includes(this.input.toLowerCase())
      );
    },
Timothee P's avatar
Timothee P committed

      if (!e.target.closest(`#custom-dropdown${this.identifier}`))
Timothee P's avatar
Timothee P committed
        this.toggleDropdown(false);
    let randomnum = Math.floor(Math.random() * 10000);
    this.identifier = randomnum;
    window.addEventListener("mousedown", this.clickOutsideDropdown);
  },

  beforeDestroy() {
    window.removeEventListener("mousedown", this.clickOutsideDropdown);
  },
};
</script>

<style scoped>
.ui.selection.dropdown .menu > .item {
  white-space: nowrap;
}
</style>