Creating an Aurelia-based auto-complete control
Published on Sunday, February 19, 2017 6:00:00 PM UTC in Programming
A while ago I created a small private web application, and instead of going the usual MVC-based way I had accustomed to during the last years, I chose to create a single-page application using Aurelia, a very sophisticated, modern, .NET developer-friendly framework for such apps. Once I reached the point where I needed some sort of auto-complete control to asynchronously fetch data from the backend to choose from, I evaluated the usual suspects I had learned to use in the past. Frankly, none of them felt "right" for the job. The style of integrating and using these controls simply seems antiquated in the light of modern web development compared to concepts like those of web components. So I thought: how hard can it be to write my own? As it turns out, not so hard. What started as a proof of concept for private use actually was a lot of fun and evolved, and today I want to share the result of that experience with others.
When I thought about what I as a developer expect from an auto-complete control, I came up with the following:
- I want to use it as a custom element (think web component)
- The component should support data binding (with the help of Aurelia) instead of fiddling with events and DOM elements
- It should nicely integrate with my preferred client-side technology: TypeScript
- I want to work with type-safe items instead of being restricted to handling dumb value-text-pairs
- Instead of just using text, it would be cool to have templating options that let me style items as I want to.
As it turned out, implementing those features was astonishingly easy using Aurelia and restricting myself to only modern browser support (read: IE11+, may work in older browsers that I didn't test). In particular, all the things I thought were difficult simply fell into place beautifully once I had carefully evaluated the options the environment and Aurelia framework provides.
Problems that were not so easy to solve mostly involved rendering details and particular behavior of (who would've thought that) different browsers regarding the "view side" of things. In particular, some features that the current state of the component offers and that, in part, were non-obvious to implement:
- Supporting CSS styling, in particular for the margins of the involved suggestion overlay for all situations
- Correctly calculating available and eventual heights of the suggestions overlay and its items
- Supporting the overlay opening upwards if not enough space is available after the input element
- Considering scroll bars for the width computation of the suggestions overlay
As you can see, all of these revolve around styling; the logic and handling other aspects like data binding, were rather uncomplicated and straight forward. The overall experience still of implementing all of this still was quite nice, never resulted in frustration on my end, and eventually ended up in something like this:
In that sample, you can see some obvious and non-obvious features:
- Custom styling (in particular, integration with Bootstrap) and custom templates, for example showing the item id in parenthesis for the item in question
- Restricting the input length value that triggers a search to a minimum character count and debouncing search requests by a configurable delay
- Keyboard navigation through items
- Forcefully hiding the suggestions (escape or using the mouse), and a visual indicator that the current value does not match the actual selected item (red border)
- Resetting the input element value to the actual selected item using the escape key
- Placeholder binding for the input element
- Creating new items on the fly (if supported)
All of this (including a demo page with various features being shown) is available using an MIT license on GitHub:
Currently a detailed documentation is missing (but partly available on that said demo page in the repository). The control however is in active use and considered stable enough for its intended use cases.
The second control that is part of the package is a multi-select control that allows tag-like selection of multiple values. You have fine control over whether it is possible to select the same value multiple times, how and when items are disabled in the suggestions list and what the visual representation of selected items (included the possibility to remove them from the selection) should look like.
For questions, feature requests or other issues, please refer to the above linked GitHub project, or use the blog's contact options.