primefaces / primevue

Next Generation Vue UI Component Library
https://primevue.org
MIT License
10.25k stars 1.21k forks source link

Autocomplete minLength is not working as expected #6399

Open DelyanNinov opened 1 month ago

DelyanNinov commented 1 month ago

Describe the bug

When setting the minLength=0 we expect the dropdown to be shown with all the options when you delete all input from the component, but the dropdown is not showing. I can't find any way to make the dropdown to appear when the user deletes all input letters. Please let me know if there is any method to show all the options when the component is cleared.

Reproducer

https://primevue4viteissuetemplate-zypu--5173--28a8ce1b.local-credentialless.webcontainer.io

PrimeVue version

4.0.1

Vue version

3.x

Language

ES6

Build / Runtime

Vue CLI App

Browser(s)

Chrome

Steps to reproduce the behavior

No response

Expected behavior

When setting minLength=0 the dropdown should appear with all options when the user deletes all input.

CCodam commented 1 week ago

That behavior is due to the following logic https://github.com/primefaces/primevue/blob/22d6f8a03724f30b6695a0800412f77a3a8ed738/packages/primevue/src/autocomplete/AutoComplete.vue#L426 If we want to accomplish the requested behavior, we would need to change the logic to

if (query.length === 0 && this.minLength !== 0) {

[!TIP] If you want a rough workaround - the options panel will blink (disappear and reappear) https://stackblitz.com/edit/7ahztt?file=src%2FApp.vue

Create a ref for the AutoComplete component.

const ac = ref();

Add ref and clear to the AutoComplete component

<AutoComplete ref="ac" @clear="acClear" v-model="value" :suggestions="items" @complete="search" :minLength="0"/>

Call show() on the AutoComplete component on the clear event

function acClear() {
  // We need to wait for the hide() function to finish (overlay to become null)
  setTimeout(function () {
    ac.value.show();
  }, 5);
}

Using a simple setTimeout is problematic, as we're just hoping that the hide() function has completed. We probably should use something like a promise instead:

function acClear() {
  // We need to wait for the hide() function to finish (overlay to become null)
  waitForHide()
    .then(() => {
      ac.value.show();
    })
    .catch((error) => {
      console.log(error.message);
    });
}

function waitForHide() {
  return new Promise((resolve, reject) => {
    const interval = setInterval(() => {
      if (!ac.value.overlay) {
        clearInterval(interval);
        clearTimeout(timeout);
        resolve();
      }
    }, 5); // Check every 5 miliseconds

    const timeout = setTimeout(() => {
      clearInterval(interval);
      reject(
        new Error(
          'Timeout: AutoComplete overlay did not become null after clear within 50 miliseconds.'
        )
      );
    }, 50); // Cancel after 50 miliseconds
  });
}