If you don't need it to be clever and dynamic, and you're not too bothered about styling, then HTML's <input> tag has a typeahead option using <datalist>.
Unfortunately its scrolling performance is kinda laggy around 200 items or so in Chrome. Here's someone's example at 5,000 options which is absurd but you might think it would perform better being that it's a native control. https://jsfiddle.net/klesun/mfgteptf/
Does this mean that every time the user types something, they have to wait a roundtrip from the server for completion? Wouldn't this make this useless for average-to-fast typers?
Htmx sounds like a lovely idea, but doesn't it introduce a ton of latency compared to client-side operations?
Well, they "wait" for a fraction of a second maybe. And you put it behind a typing delay so it responds only when the user is ready.
Also, many autocompletes do a round trip anyway. The htmx version just returns the html already rendered, rather than, say, JSON that requires further processing and injecting.
Here are a couple of Go templates from a sample project that show it:
In response to `/autoc/<id>/search`, the server just responds with a list of strings matching the user's input, formatted with the `autoc_data` template. Htmx injects that into the `<datalist>` directly.
It's how any search engine does autocompletes... you can't possibly store all the queries clientside. Whether you're sending a tiny JSON or a tiny HTML snippet back doesn't really make much of a difference. It's usually fast enough, especially if you debounce/throttle the user input so you're not sending the query on every keystroke.
In my experience type ahead is most useful on datasets that are generally too large to load the whole dataset locally. There are certainly times when a list is too long to fit in the available space, but unlikely to grow unbounded, but such large lists that are known not to grow in an unbounded manner are rare in my experience.
"Not too bothered about styling" is quite important. Datalists are relatively uncommon and I think many users may not know what they are seeing and how they can interact with it.
Also datalists appear quite different across different browsers, which is fine of course for a native form control, but annoying if you're aiming for a more consistent look.
I just wish that you could natively do something that works more like select elements, so users see the contents of the option elements but the value of the option element is actually what is populated in the form.
The option and the form will work that way, but the input itself will then show the value instead of the option label... the input is not smart enough to present the option as a select does, it shows whatever you have in the "value" field.
At least on Edge, it got continuous substring matching right (illa shows vanilla), but failed to get the most important type of matching: arbitrary substring. Not a surprise, I only know a couple editors that support it. But it's truly the ideal form of filtering, especially when the entries are long. Think css, how much nicer would it be to type "mato" in devtools and get "margin-top"? Or, the ideal case that is somehow still missing – browser history entries: type the first char or two of the hostname, one or two from the path, and a couple form the query, and you've filtered everything down to just one or two options.
> Think css, how much nicer would it be to type "mato" in devtools and get "margin-top"?
I can't say that this type of search has ever crossed my mind. This type of search would seem to me to be greatly ambiguous. For example, if you have "tomato" in the corpus then that obviously supercedes "margin-top" for the search string "mato". If you know the entire corpus, then I suppose you can take advantage of shortcuts like this when you know there is only one match, but then again it would seem to me that simply writing "margin-top" would require less mental gymnastics.
If you've ever used any filtering in VS Code, this is the algorithm. Re tomato/margin-top, weight is given to matching the prefix exactly, so margin-top does indeed rank higher.
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/da...