Update: I’ve now released a new version of the Typeahead which supports Blazors forms and validation. I’ve updated this post accordingly as there were some breaking changes. Check out the repo for full details.
This week I thought I’d give an overview of the most recent addition to the Blazored collection, Blazored.Typeahead.
For those for you not familiar with Blazored, it’s a collection of components and libraries to help with developing Blazor applications. There are libraries such as Blazored.LocalStorage and Blazored.SessionStorage which wrap browser APIs with C# APIs, so you don’t have to. Then there are components such as Blazored.Modal and Blazored.Toast which save you having to build common UI features.
What is Blazored.Typeahead
Blazored.Typeahead is flexible autocomplete/typeahead/suggestion component for Blazor applications. Which looks like this…
Features
Here are some of the key features of the component.
Forms Integration
There are two versions of the component, standalone and forms integrated. The first is designed to work independently while the second will only work with Blazor built-in forms and validation components.
Searching Data
The primary feature of the component is in the way it handles searching. You provide the component with a search method which it will call with the search text entered. This means you’re in full control of where your data comes from, it could be a local collection or it could be the result of an API call.
Debounce Control
The control has built in debounce functionality which delays searches being performed until a period of inactivity has been reached. This is extremely useful when calling external APIs for searching as performing a search on every keypress would not be a good thing, especially for long queries.
Templating
Developers are able to provide templates for the following things.
- Selected result
- Search result
- Not found result
This allows total control over how the results look and you can make them as rich and stylish as you want.
Getting Started
Now we’ve looked at a few of the features let’s look at how to get the component into a Blazor application.
Installing
Just like all Blazored packages, Blazored.Typeahead is available on NuGet. You can add it to your apps by either searching for it in the package explorer in Visual Studio.
Or if you prefer the command line, you can install it via the Package Manager Console or dotnet CLI using the following commands, respectively.
Install-Package Blazored.Typeahead
dotnet add package Blazored.Typeahead
Once the package is installed I would suggest adding the following using statement to your main _Imports.razor
. This will save you having to use the fully qualified name when using the component.
@using Blazored.Typeahead
You will also need to add the following tag to the head
tag of either the _Host.cshtml
or index.html
file, depending on if you’re running a Blazor Server App or a Blazor WebAssembly App.
<link href="_content/Blazored.Typeahead/blazored-typeahead.css" rel="stylesheet" />
As well as the following script tag at the bottom.
<script src="_content/Blazored.Typeahead/blazored-typeahead.js"></script>
Configuration Options
In order to use the component there are a few required parameters and templates that must be provided. There are also several optional parameters which allow you to fine tune the components behaviour.
Parameters
Value
(Required) - The item to bind the selected result toSearchMethod
(Required) - The Method to call when performing a searchPlaceholder
(Optional) - Allows developer to specify a placeholder messageMinimumLength
(Optional | Default 1) - Minimum number of characters required before starting a searchDebounce
(Optional | Default 300) - Time to wait after last keypress before starting a search
Templates
ResultTemplate
(Required) - Allows the user to define a template for a result in the results listSelectedTemplate
(Required) - Allows the user to define a template for a selected itemNotFoundTemplate
- Allows the user to define a template when no items are found
Usage Example
In this example, we’ll look at the minimum needed to get up and working. Most settings on the component have default values, the only things that must be specified are:
SearchMethod
- The method which will be called to perform the searchValue
- The item to bind the selected result toSelectedTemplate
- The template to use to display the selected itemResultTemplate
- The template to use to when displaying search results
To keep things simple we’ll be querying a local collection of Films.
<BlazoredTypeahead SearchMethod="SearchFilms"
@bind-Value="SelectedFilm">
<SelectedTemplate>
@context.Title
</SelectedTemplate>
<ResultTemplate>
@context.Title (@context.Year)
</ResultTemplate>
</BlazoredTypeahead>
@if (SelectedFilm != null)
{
<p>Selected Film is: @SelectedFilm.Title</p>
}
@code {
private List<Film> Films;
private Film SelectedFilm;
protected override void OnInitialized()
{
Films = new List<Film> {
new Film("The Matrix", 1999),
new Film("Hackers", 1995),
new Film("War Games", 1983) };
}
private async Task<IEnumerable<Film>> SearchFilms(string searchText)
{
return await Task.FromResult(Films.Where(x => x.Title.ToLower().Contains(searchText.ToLower())).ToList());
}
class Film
{
public string Title { get; set; }
public int Year { get; set; }
public Film(string title, int year)
{
Title = title;
Year = year;
}
}
}
The key thing to note in the code above is the SearchFilms
method. This is what the typeahead is calling to perform the search. This method must have the following signature.
Task<IEnumerable<T>> MethodName(string searchText)
This gives us lots of flexibility on how data is sourced and queried. For example, we could change the SearchFilms
method to query an API instead.
private async Task<IEnumerable<Film>> SearchFilms(string searchText)
{
var result = await httpClient.GetJsonAsync<List<Film>>($"https://awesomefilmsearch.com/api/films/?title={searchText}");
return result;
}
Forms Integration
The current version of the control does not yet integrate with the forms and validation provided in Blazor. This is the next feature to be worked on and I’m hoping this will be done shortly.
Blazored.Typeahead now supports forms integration without any additional setup or code changes. Just put it inside of a EditForm
component and it will just work as expected.
<EditForm Model="@FormModel" OnValidSubmit="HandleFormSubmit">
<DataAnnotationsValidator />
<BlazoredTypeahead SearchMethod="GetPeopleLocal"
@bind-Value="FormModel.SelectedPerson"
Placeholder="Search by first name...">
<SelectedTemplate Context="person">
@person.Firstname
</SelectedTemplate>
<ResultTemplate Context="person">
@person.Firstname @person.Lastname
</ResultTemplate>
</BlazoredTypeahead>
<ValidationMessage For="@(() => FormModel.SelectedPerson)" />
<button class="btn btn-primary" type="submit">Submit</button>
</EditForm>
Summary
That’s about it for Blazored.Typeahead! If you like what you see then please go and add it to your Blazor project. This is still an early version of the component so if there are any features you would like to see, or if you find a bug, then please head over the GitHub repo and open an issue and we can have a chat about it.