stimulus-autocomplete icon indicating copy to clipboard operation
stimulus-autocomplete copied to clipboard

Suggestion: Allow to use local HTML instead of fetching from the server

Open fidalgo opened this issue 1 year ago • 3 comments

Hi! First of all, thank you for your work on this!

If we allow using HTML data attributes with data in JSON format instead of fetching from the server, this will allow caching where the data is static while preventing more network requests.

Imagine the case of a country list, where it's a fixed list; we may want just to iterate and render the li elements, but currently, we cannot use the autocomplete.

Do you think this could be a nice addition to this lib?

fidalgo avatar Aug 26 '22 20:08 fidalgo

I just tried abusing a data URL for this:

<div data-controller="autocomplete" data-autocomplete-url-value="data:text/html,%3Cli%20class%3D%22list-group-item%22%20role%3D%22option%22%20data-autocomplete-value%3D%221%22%3EBlackbird%3C%2Fli%3E%0A%3Cli%20class%3D%22list-group-item%22%20role%3D%22option%22%20data-autocomplete-value%3D%222%22%3EBluebird%3C%2Fli%3E%0A%3Cli%20class%3D%22list-group-item%22%20role%3D%22option%22%20data-autocomplete-value%3D%223%22%3EMockingbird%3C%2Fli%3E%0A">
    <input name="birds" type="text" class="form-control" data-autocomplete-target="input" placeholder="search a bird" autofocus/>
    <input type="hidden" name="bird_id" data-autocomplete-target="hidden"/>
    <ul data-autocomplete-target="results" class="list-group"></ul>
</div>

It works partially 🤣 The query parameters obviously become part of the answer.

https://user-images.githubusercontent.com/245443/191965163-8efcc89e-3aeb-4fcd-85e1-becdcb511e6a.mp4

schmijos avatar Sep 23 '22 12:09 schmijos

@fidalgo if you just want to solve this issue for a particular feature you could override doFetch in the controller to return an HTML with the options you want to show.

<div data-controller="combobox" data-combobox-options-value="[JSON array with options]">
...
</div>
class Combobox extends Autocomplete {
  static values = { options: Array }

  doFetch = async () => {
    const query = this.inputTarget.value.trim().toLowerCase()
    const matchingOptions = this.optionsValue.filter(o => o.toLowerCase.includes(query))
    return matchingOptions.map(o => `<li data-autocomplete-value="${o}">${o}</li>`).join("\n")
  }
}

If however you wan to add the feature to the library, I'd suggest going in the opposite direction: create a base Combobox class that allows filtering a set of static options and then define Autocomplete as a subclass of Combobox, adding the methods to fetch new options from the server in Autocomplete.

I'd be happy to accept patches implementing that, although it seems a substantial change.

afcapel avatar Sep 23 '22 15:09 afcapel

+1

ACPK avatar Feb 28 '23 19:02 ACPK