Blazor - Add search box to simple data grid
Use case: User want
to be able to search the records for matching data. The user does not want to have to learn
complex query syntax or a coded language.
They want our search to work like Googles, you just type in words and it
finds it for you.
Now that we have a usable data grid for our applications, [SimpleGrid], we will be adding a search box to it.
These are the steps we will need to take to add a search box to our
application.
1.
Add the UI
2.
Wire in the On click event
3.
Allow the user to “clear” the search results
Before Search View
Search Box UI
There is nothing really special about our search box HTML:
<div class="row searchactionrow">
<div class="col-md-6">
<div class="input-group">
<input type="text" class="form-control" name="x" placeholder="Search term..." @bind="searchTerm" >
<span class="input-group-btn">
<button class="btn btn-default" @onclick='Search' type="button"><span class="fas fa-search"></span> </button>
@if (filterOn)
{
<button type="button" class="btn btn-link" @onclick='ClearFilter'>Clear Filter</button>
}
</span>
</div>
</div>
</div>
We have an input box that is data bound to the variable, “searchTerm”. We are using font awesome for the search magnifying
glass icon. We added a link button for
the “clear” filter button so the user can clear out the search results and set
the data grid back to all records.
The “searchactionrow” CSS just adjusts the padding around the
search box.
Wire in the Search Onclick Event
This is where the cool part of Blazor shows off. We create the method “Search” and wire in the
actual search:
protected void Search()
{
if (searchTerm.IsNotEmpty())
{
filterOn = false;
var t = dataCollection
.Where(x => x.Summary.ToLower().Contains(searchTerm))
.Union(from c in dataCollection
.Where(x => (x.TemperatureC.ToString() ?? null).ToLower().Contains(searchTerm))
select c)
.Union(from c in dataCollection
.Where(x => (x.TemperatureF.ToString() ?? String.Empty).ToLower().Contains(searchTerm))
select c)
.Union(from c in dataCollection
.Where(x => (x.Date.ToLongDateString() ?? String.Empty).ToLower().Contains(searchTerm))
select c);
if (t.Any())
{
data = t.ToList();
filterOn = true;
}
searchTerm = "";
this.StateHasChanged();
}
}
This is a fairly simple way to do a quick search of all the fields
in a collection of objects. If your
collection is small, less than a million, this is a perforate solution. We
take the search term the user entered, then check each for a match. We are looking for case insensitive matches, so
we will ToLower the search term and the field values. We need to make sure that we skip fields with
null values, (x.Field ?? null). For
dates, we are going to use long date string, so if a user enters in “Dec” they
will find matches. It is noted that
search by date ranges would need to be implemented differently.
We check if we found any matching records. If so, we set them to the variable data, this
is collection the gird display from. We
then clear out the search term and update the UI with a this.StateHasChange call.
After Search
You can see that our search worked, but the UI still shows
100 Records and the pagination. We need
to re-calculate those after the search, so we don’t confuse the user.
We make a change to the search method. If we have results, we will need to do 2 things,
re-calculate the paging and set the number of “Filter” records. We can re-calculate the paging by call our grid
service:
gridService.PageCount =
gridService.GetPageCount(gridService.PageSize, t.ToList().Count);
Next, we need to add a new variable, filteredRecordCount and
set it to the number of matching search records. We will display this right above the total
records count.
filteredRecordCount = t.ToList().Count;
Now let’s look at the new search results:
Nice and clean. We did
add a UI element to let the users know when there was no matches in the search. It just show a message in red.
<h4 class="noresults">@searchMessage</h4>
Clear the Search Results
We need to add the ability for the user to “Clear out” the
search result and get back to the full records set. In the UI we added the Link button for this.
@if (filterOn)
{
<button type="button" class="btn btn-link" @onclick='ClearFilter'>Clear Filter</button>
}
Set the filter flag off, clear out the search term, set the
UI data collection to the full collection and then update the UI. And we are back to the full record set.
Bonus
While building the search box, I decided it would be cool to
allow the user to simply hit the “Enter” key after entering in the search
term. I just needed to hook up a handler
to the onkeyup event on the search term input element. It needs to be noted that you have to use the
“onkeyup” event so you can capture the special keys, such as backspace.
private void RunLookup(KeyboardEventArgs e)
{
if (e.Key.Match("enter"))
{
Search();
searchTerm = "";
}
else if(e.Key.Match("backspace"))
{
if (searchTerm.Length > 0)
{
searchTerm = searchTerm.Substring(0, searchTerm.Length - 1);
}
}
else
{
searchTerm += e.Key;
}
}
On each key press, we are looking to see if enter was
pressed. If so, we execute the
search. If the user hit the backspace,
we remove the last char of the search string if the string is not empty. If it was not the enter or backspace key, we
add the character to the search term string.
This was a cool feature to add to the simple grid that gives
it a lot more power. When I start
building out my UI component library, future post, I will need to include my
search box.
Comments
Post a Comment