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"
      class="search"
      autocomplete="off"
      tabindex="0"
      @input="handelInput"
      v-on:keyup.enter="select(0)"
      v-model="input"
      :placeholder="placeholder"
    />
    <!-- {{placeholder}} -->
    <div class="default text">{{ selected || placeholder }}</div>
    <i
      :class="['dropdown icon', { clear: search && selected }]"
      @click="clear"
    ></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;
    },
  },

  data() {
    return {
      isOpen: false,
      input: "",
      identifier: 0,
    };
  },
  methods: {
    toggleDropdown() {
      this.isOpen = !this.isOpen;
    },
    select(index) {
      setTimeout(() => {
        this.isOpen = false; // * quick & dirty, car toggle dropdown est rappelé plusieurs fois aileurs, à creuser...
      }, 500);
      this.$emit("update:selection", this.options[index]);
      this.input = "";
    },
    searchOptions(options) {
      return options.filter((el) =>
        el.toLowerCase().includes(this.input.toLowerCase())
      );
    },
    clear() {
      if (this.search) {
        this.input = "";
        this.clearSelected();
      }
    },
    clearSelected() {
      this.$emit("update:selection", "");
    },
    handelInput() {
      this.isOpen = true;
      this.clearSelected();
    },
    clickOutsideDropdown(e) {
      if (!e.target.closest(`#custom-dropdown${this.identifier}`))
        this.isOpen = 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>