How do I use IndexedDB in Blazor WebAssembly?

Platform: Blazor|Category : General, WebAssembly

IndexedDB is used for the client-side storage of data and files. Follow these steps to use IndexedDB in Blazor WebAssembly:

  1. Create a Blazor WebAssembly app and install the IndexedDB.Blazor NuGet package using the NuGet package manager.

  2. Set up the IIndexedDbFactory configuration service in your Program.cs file and set it as scoped.
    [Program.cs]

    using IndexedDB.Blazor;
    builder.Services.AddScoped<IIndexedDbFactory, IndexedDbFactory>();
    
  3. Now add the properties inside the class to store and process data in the Data folder.
    [IndexDb.cs]

    using IndexedDB.Blazor; 
    using Microsoft.JSInterop; 
    using System.ComponentModel.DataAnnotations;
    namespace Blazor_WebAssembly_App.Data 
    {
    	public class IndexDb : IndexedDb
    	{
    		public IndexDb ( IJSRuntime jSRuntime, string name, int version ) : base(jSRuntime, name, version) { }
    		// These are like tables. Declare as many of them as you want.
    		public IndexedSet<Employee> employee { get; set; }
    	}
    	public class Employee
    	{
    		[Key]
    		public int Id { get; set; }
    		[Required]
    		public string? FirstName { get; set; } 
    		[Required]
    		public string? LastName { get; set; }
    	}
    }
    
  4. Add the namespace for the IndexedDB in _Import.razor file.
    [_Import.razor]

    @using IndexedDB.Blazor 
    @using {{Your_App_Name}}.Data
    
  5. Add the Razor component to add and store the data using IndexedDB in the Index.razor file.
    [_Import.razor]

    @page "/" 
    @inject IIndexedDbFactory DbFactory 
    <h1>employee</h1> 
    @if (employee != null)
    {
    	<table class="table">
    		<thead>
    			 <tr>
    				<th>ID</th>
    				<th>First name</th>
    				<th>Last name</th>
    				<th></th> <!-- Delete column -->
    			</tr>
    		</thead>
    		<tbody>
    			@foreach (var Employee in employee)
    			{
    				<tr>
    					<td>@Employee.Id</td>
    					<td>@Employee.FirstName</td>
    					<td>@Employee.LastName</td>
    					<td>
    						<button class="btn btn-danger" @onclick="() => DeleteEmployee(Employee.Id)">Delete</button>
    					</td>
    				</tr>
    			}
    		</tbody>
    	</table>
    }
    <fieldset> 
    	<legend>Add new Employee</legend>
    	<EditForm Model="@newEmployee" OnValidSubmit="@SaveNewEmployee">
    		<InputText @bind-Value="@newEmployee.FirstName" placeholder="First name..." />
    		<InputText @bind-Value="@newEmployee.LastName" placeholder="Last name..." />
    		<button type="submit">Add</button>
    		<p><ValidationSummary /></p>
    		<DataAnnotationsValidator />
    	</EditForm>
    </fieldset>
    @code {
    	List<Employee>? employee;
    	protected override async Task OnInitializedAsync ()
    	{
    		await RefreshEmployeeList();
    	}
    	Employee newEmployee = new Employee();
    	async Task RefreshEmployeeList ()
    	{
    		using var db = await DbFactory.Create<IndexDb>();
    		employee = db.employee.ToList();
    	}
    	async Task SaveNewEmployee ()
    	{
    		using var db = await this.DbFactory.Create<IndexDb>();
    		db.employee.Add(newEmployee); 
    		await db.SaveChanges();
    		// Refresh list and reset the form
    		newEmployee = new Employee();
    		await RefreshEmployeeList();
    	}
    	async Task DeleteEmployee ( int id )
    	{
    		using var db = await this.DbFactory.Create<IndexDb>();
    		var employeeToDelete = db.employee.FirstOrDefault(e => e.Id == id);
    		if (employeeToDelete != null)
    		{
    			db.employee.Remove(employeeToDelete);
    			await db.SaveChanges();
    			await RefreshEmployeeList();
    		}
    	}
    }
    

View Sample in GitHub