<template> <div :id="`custom-dropdown${identifier}`" :class="[ 'ui search selection dropdown', { 'active visible': isOpen }, { disabled }, ]" @click="toggleDropdown" > <input v-if="search" v-model="input" v-on:keyup.enter="select(0)" v-on:keyup.esc="toggleDropdown(false)" class="search" autocomplete="off" tabindex="0" :placeholder="placehold" ref="input" /> <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} let options = this.options.map((el) => el.constructor === Object ? el.name : el ); if (this.search && this.input !== "") { options = this.searchOptions(options); } return options.length > 0 ? options : null; }, }, data() { return { isOpen: false, input: "", identifier: 0, }; }, methods: { 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; }, select(index) { // * toggle dropdown is called several time, timeout delay this function to be the last setTimeout(() => { this.isOpen = false; }, 0); this.$emit("update:selection", this.options[index]); this.input = ""; }, searchOptions(options) { return options.filter((el) => el.toLowerCase().includes(this.input.toLowerCase()) ); }, clickOutsideDropdown(e) { if (!e.target.closest(`#custom-dropdown${this.identifier}`)) this.toggleDropdown(false); }, }, created() { 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>