0

I’m having a small issue with some custom blur and focus behaviours, using the vue-select component.

I’m attempting to override the blur behaviour of the component, if a user clicks away and onto a specific, predefined target - for example, if the user clicks onto #special-place while a select is open, the select should remain open until any other element receives focus.

The code below gets me most of the way there, but there is a small bug: if a dropdown is open and another select component is clicked, the second one remains then open regardless of any subsequent clicks. Here’s a sandbox, with a live example.

Template is as follows:

<template>
  <v-select
    @search:blur="customBlurHandler"
    :options="options"
    :filterable="false"
    :ref="reference"
    :placeholder="placeholder"
    label="name"
  >
    <!-- Remove caret icon -->
    <div slot="open-indicator"></div>
  </v-select>
</template>

The relevant methods are below (not the best named, I know):

export default {
  data() {
    return {
      options: ["one", "two", "three"],
      isBlurHandlerActive: false,
      reference: `${this.locationType}Select`
    };
  },
  props: ["locationType", "placeholder"],
  name: "CustomSelector",
  components: { vSelect },

  methods: {
    clickHandler(event) {
      const specialClicked = event.target.closest("#special-place") !== null;
      if (specialClicked) return;
      else {
        this.isBlurHandlerActive = true;
        document.removeEventListener("click", this.clickHandler);
        this.forceOptionsClosed();
      }
    },

    customBlurHandler() {
      if (this.isBlurHandlerActive) {
        this.isBlurHandlerActive = false;
        return;
      } else {
        this.forceOptionsOpen();
        document.addEventListener("click", this.clickHandler);
      }
    },

    forceOptionsClosed() {
      this.$refs[this.reference].open = false;
      this.$refs[this.reference].searchEl.blur();
    },

    forceOptionsOpen() {
      this.$refs[this.reference].open = true;
      this.$refs[this.reference].searchEl.focus();
    }
  }
};

I’m also aware this might not be the most vue-like way to approach the problem, so if there’s a better way to solve this, I’m open to suggestions.

verism
  • 1,106
  • 1
  • 12
  • 35

0 Answers0