vueform / multiselect

Vue 3 multiselect component with single select, multiselect and tagging options (+Tailwind CSS support).
https://vueform.com
MIT License
808 stars 151 forks source link

Cannot set focus via the API #299

Closed FichteFoll closed 1 year ago

FichteFoll commented 1 year ago

Version

Description

I want to force-re-open the dropdown after the clear icon has been clicked to prompt the user to fill it in again. If the dropdown is then closed without making a selection, I intend to set all available options as active so simulate a "select all" operation since the value should not be empty.

Trying to activate the component with the exposed API methods does not work as advertised, but generally the element doesn't actually take focus and instead only shows as if it had focus. Clicking outside of the open dropdown does not close it either. The only way to "fix" the state is by clicking somewhere within the component, which it interprets normally and seems to correct its internal state. This works neither from the @close handler nor from the console in dev mode via $vm.$refs.multiselect.focus() and related.

Demo

Unable to get JSFiddle to behave, but I used the following SFC to replicate:

<script setup lang="ts">
import { ref, nextTick, type Ref } from 'vue';

import Multiselect from '@vueform/multiselect/dist/multiselect.vue2.js';

let options = [
  { label: 'test', value: 1 },
  { label: 'test2', value: 2 },
  { label: 'test3', value: 3 },
]
let value = ref([]);

const multiselect: Ref<Multiselect | null> = ref(null)

function onClear() {
  console.log("onClear", multiselect.value);
  // multiselect.value?.focus(); // doesn't do anything
  // multiselect.value?.open(); // opens dropdown without showing as active but is without focus
  // multiselect.value?.activate(); // opens dropdown and shows as active but is without focus

  // wrapping with nextTick doesn't change anything either
  // nextTick(() => multiselect.value?.focus());
  // nextTick(() => multiselect.value?.open());
  // nextTick(() => multiselect.value?.activate());
}
</script>

<template>
  <div>
    <input type="text" />
    <button @click="multiselect?.open()">open</button>
    <button @click="multiselect?.activate()">activate</button>
    <button @click="multiselect?.focus()">focus</button>
    <p>
      Multiselect
    </p>
    <Multiselect
      v-model="value"
      :options="options"
      mode='tags'
      :close-on-select="false"
      @clear="onClear"
      ref="multiselect"
    />
    <br>
    <input type="text" />
  </div>
</template>

<style src="@vueform/multiselect/themes/default.css"></style>

The API functions can be triggered via the three buttons or by clearing the multiselect (where one should be choosed by commenting the others). The extra inputs are to have something to focus with tab and the mouse to show how the multiselect doesn't lose its focused state.

adamberecz commented 1 year ago

This should now work in2.5.8. If not feel free to reopen.

FichteFoll commented 1 year ago

I just tested it with the same component as above but updated to the latest version and I don't see any change in behavior, unfortunately.

FichteFoll commented 1 year ago

This is probably also related to the dropdown closing itself after the browser window loses focus (also when clicking on the dev tools, for example) and then clicking on the input does not re-open it. You need to click away somewhere inside the page first and only then does the dropdown open when you click on the input again.

FichteFoll commented 1 year ago

I just tested it with the same component as above but updated to the latest version and I don't see any change in behavior, unfortunately.

Quick update here that I cannot reproduce the initially reported problem anymore, so I was probably just testing incorrectly. I now get the desired behavior by calling .activate() and .focus() in the onClear handler (focus is necessary for :searchable="true".

The behavior in the other comment can probably be explained by the searchable mode where clicking inside the input after focus on the window has been lost does not re-open the dropdown. I'll create a separate issue if it bothers me enough.