Introduction

The search function is a frequently used feature in web development that increases user-friendliness and enables quick access to relevant data. In this post, we will create a simple and powerful reusable Blazor search component that can be integrated into your project via multiple parts. This not only saves development time, but also ensures consistency in design and behavior.

In the previous post we created a reusable Blazor select component, and in this post we continue creating our reusable Blazor components library that can be integrated into your various projects.

Take a look at the finished Blazor select component implemented in a Blazor Web App.

<DncSearch TItem="Employee" OnSearch="HandleSearch" PlaceholderText="Search...." ButtonText="Search"/>
https://dotnetcoder.com/wp-content/uploads/2024/08/Creating-a-Reusable-Blazor-Search-Component.webm

Prerequisites

Before we start, ensure you have the following installed:

  • NET 8 SDK
  • Visual Studio 2022 (or another preferred IDE)
  • Basic understanding of Blazor (Components, Data Binding, Event Handling)

Setting Up the Project

Open Visual Studio and create a blank solution named Search . Add a new Razor Class library named Dnc.Common.Razor to the solution. Select .NET 8 (Long Term Support) as the target Framework.

Creating a Reusable Blazor Search Component project and adding a razor class library

Creating the Blazor search component

First, create a new folder in theDnc.Common.Razor project named Search. Then, create a new class file called DncSearchComponent derived from the ComponentBase class, and identify it as a generic class with a single generic parameter called TItem, and add the following code.

namespace Dnc.Common.Razor.Search
{
    public class DncSearchComponent<TItem> : ComponentBase
    {
        [Parameter]
        public EventCallback<string> OnSearch { get; set; }

        [Parameter]
        public string PlaceholderText { get; set; } = "Search...";

        [Parameter]
        public string ButtonText { get; set; } = "Search";

        [Parameter]
        public string CssButton { get; set; } = "btn-primary";

        protected string searchTerm;

        protected async Task HandleSearch()
        {
            await OnSearch.InvokeAsync(searchTerm);
        }

        protected async Task HandleEnter(KeyboardEventArgs e)
        {
            if (e.Key == "Enter")
            {
                await OnSearch.InvokeAsync(searchTerm);
            }
        }
    }
}

We will go over the code and provide some explanation.

The EventCallback<string> OnSearch is used for the communication between the DncSearchComponent and the parent component. In our case, it will handle the click event triggered by the Blazor search component.

The PlaceholderText and ButtonText parameters are used to set the text for the input field placeholder and the text button , while the CssButton parameter is used to set the style for the search button.

The HandleSearch method triggers the OnSearch custom event when the search button is clicked , while the HandleEnter method triggers the OnSearch custom event when Enter is clicked.

The markup of the Blazor search component is simple and self-explanatory. In the Search folder, create a new file called DncSearch.razor, which inherits from the DncSearchComponent class, and enter the following markup.

Also read https://dotnetcoder.com/building-a-reusable-blazor-select-component/

@inherits DncSearchComponent<TItem>
@typeparam TItem

<div class="dnc-search">
    <i class="fa fa-search dnc-search-icon"></i>
    <input @bind="searchTerm" @onkeyup="@HandleEnter" type="text" class="form-control" placeholder="@PlaceholderText">
    <button @onclick="HandleSearch" class="btn @CssButton">@ButtonText</button>
</div>

Finally, create a new stylesheet file in the Search folder calledDncSearch.razor.css and add the following styles.

.dnc-search {
    position: relative;
    box-shadow: 0 0 40px rgba(51, 51, 51, .1);
}

    .dnc-search input {
        height: 60px;
        text-indent: 25px;
        border: 2px solid #d6d4d4;
    }


        .dnc-search input:focus {
            box-shadow: none;
            border: 2px solid blue;
        }


    .dnc-search .dnc-search-icon {
        position: absolute;
        top: 20px;
        left: 16px;
    }

    .dnc-search button {
        position: absolute;
        top: 5px;
        right: 5px;
        height: 50px;
        width: 110px;
    }

.btn-primary {
    background: blue;
}

Using the Blazor Search component in a Blazor Web App

To see our Blazor Search component in action, we will test it in a simple Blazor web app .

First, add a new Blazor Web App project template called Dnc.Search.WebApp to the solution. I have selected .NET 8 (Long Term Support) as the target Framework.

Adding the Blazor web app to the Search project to see the blazor search component in action.

Second reference the Dnc.Common.Razor project to the  Dnc.Search.WebApp project, and update the _Imports.razor as follows.

// Removed code for brevity
@using Dnc.Common.Razor.Search
@using Dnc.Search.WebApp.Models

Then  include the bootstrap link in the App.razor file, as shown below.

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css">

Finally, add the following code to the Home.razor file and run the application.

@page "/"
@using System.Text.Json

<PageTitle>Home</PageTitle>

<h1 class="dnc-center">Blazor Reusable Search Component</h1>

<div class="container">
    <DncSearch TItem="Employee" OnSearch="HandleSearch" PlaceholderText="Search...." ButtonText="Search"/>
    @if (employees != null)
    {
        <table class="table my-5">
            <thead>
                <tr>
                    <th scope="col">Id</th>
                    <th scope="col">Name</th>
                    <th scope="col">Age</th>
                    <th scope="col">Gender</th>
                    <th scope="col">Designation</th>
                    <th scope="col">Department</th>
                </tr>
            </thead>
            @foreach (var employee in filteredEmployees)
            {
                <tbody>
                    <tr>
                        <td>@employee.Id</td>
                        <td>@employee.Name</td>
                        <td>@employee.Age</td>
                        <td>@employee.Gender</td>
                        <td>@employee.Designation</td>
                        <td>@employee.Department</td>
                    </tr>
                </tbody>
            }
            @if (filteredEmployees.Count == 0)
            {
                <tr>
                    <td colspan="6">
                        <p class="dnc-center">No data found</p>
                    </td>
                </tr>
            }
        </table>
    }
</div>

@code{
    private List<Employee> employees;
    private List<Employee> filteredEmployees;

    protected override async Task OnInitializedAsync()
    {
        employees = await GetEmployees();
        filteredEmployees = employees;
    }

    private async Task<List<Employee>> GetEmployees()
    {
        var json = await File.ReadAllTextAsync(@"./Data/employees.json");
        return JsonSerializer.Deserialize<List<Employee>>(json, options: new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
    }

    private void HandleSearch(string searchTerm)
    {
        if (string.IsNullOrEmpty(searchTerm))
        {
            filteredEmployees = employees;
        }
        else
        {
            filteredEmployees = employees.Where(v => 
                v.Name.Contains(searchTerm, StringComparison.OrdinalIgnoreCase) ||
                v.Age.ToString().Contains(searchTerm, StringComparison.OrdinalIgnoreCase) ||
                v.Gender.Contains(searchTerm, StringComparison.OrdinalIgnoreCase) ||
                v.Designation.Contains(searchTerm, StringComparison.OrdinalIgnoreCase) ||
                v.Department.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)
            ).ToList();
        }
    }
}

The GetEmployees method is used to get the data from the json file found in the project code on my GitHub repository, while the HandleSearch method is used to filter the data when the search button is clicked in the Blazor search component.

Blazor search component in action

Also read https://dotnetcoder.com/blazor-server-app-authentication-with-entra-id/

Conclusion

By creating a reusable search component, you can streamline development, ensure consistency in your application and reduce redundancy.
 In this post, we created a Blazor search component that you can use in your various projects. This component can be extended to meet your project requirements.

Sample Code

You can find the complete sample code for this project on my GitHub repository

Author

Exit mobile version