Home / Blazor Web Assembly / Custom Modal Pop up component using Blazor Web Assembly and .NET6

Custom Modal Pop up component using Blazor Web Assembly and .NET6

Last updated on April 16th, 2023

Estimated reading time: 8 minutes

In web applications there is often an requirement to display data in modal up. Traditionally modal pop ups are implemented using JavaScript frameworks. In this article you will learn to Custom Modal Pop up component using Blazor Web Assembly and .NET6 using C#.

Note: Basic working knowledge of Blazor web assembly and .NET Core is required for this working demo. If you are new to Blazor read article on creating a fully functional application in Blazor web assembly with Add/Edit/Delete operations.

CRUD Operations Using Blazor Web Assembly, .NET 6.0, Entity Framework Core

Output

 Modal popup with validation messages would be display as below.

Modal pop up

Create custom modal pop up component

Create a new Blazor web assembly project with .NET Core hosted . Select .NET 6 Framework . The basic project structure is as shown below.

project structure
  • EmployeePortal.Client is Blazor Web assembly Project
  • EmployeePortal.Server is .NET6 server Project to host API and Database Repository
  • EmployeePoral.Shared is .NET Standard Library Project. Entity models would reside in this project and it would be shared by client and server project

Create a new component folder in our client project and add new Razor component. The detailed structure of client folder is mentioned below.

blazor projecct

Add the below code in AddEmployeeDialog.razor

@if (ShowDialog)  
{  
  
<div class="modal fade show d-block" id="exampleModal" tabindex="-1" role="dialog">  
    <div class="modal-dialog" role="document">  
        <div class="modal-content">  
            <div class="modal-header">  
                <h5 class="modal-title" id="titleLabel">Add Employee</h5>  
                <button type="button" class="close" @onclick="@Close" data-dismiss="modal" aria-label="Close">  
                    <span aria-hidden="true">×</span>  
                </button>  
            </div>  
            <div class="modal-body">  
                <EditForm Model="@Employee" OnValidSubmit="@HandleValidSubmit">  
                    <DataAnnotationsValidator />  
                    <ValidationSummary />  
                    <div class="form-group">  
                        <label for="lastName">Last name: </label>  
                        <InputText id="lastName" class="form-control" @bind-Value="@Employee.LastName" placeholder="Enter last name"></InputText>  
                        <ValidationMessage For="@(() => Employee.LastName)" />  
                    </div>  
                    <div class="form-group">  
                        <label for="firstName">First name: </label>  
                        <InputText id="firstName" class="form-control" @bind-Value="@Employee.FirstName" placeholder="Enter first name"></InputText>  
                        <ValidationMessage For="@(() => Employee.FirstName)" />  
                    </div>  
                    <div class="form-group">  
                        <label for="email">Email: </label>  
                        <InputText id="email" class="form-control" @bind-Value="@Employee.Email" placeholder="Enter email"></InputText>  
                        <ValidationMessage For="@(() => Employee.Email)" />  
                    </div>  
                    <button type="submit" class="btn btn-primary">Save employee</button>  
                    <a class="btn btn-outline-primary" @onclick="@Close">Close</a>  
                </EditForm>  
            </div>  
        </div>  
    </div>  
</div>  
}  

DataAnnotationsValidator is a built-in validation component in Blazor, which is used to validate user input using data annotations. Data annotations are attributes that are applied to model properties to specify validation rules.

To use the DataAnnotationsValidator component in Blazor, you need to follow these steps:

Apply data annotations to the model properties that you want to validate. For example, you can apply the Required attribute to a property to indicate that it cannot be empty. In your Blazor component, add the DataAnnotationsValidator component. Use the ValidationMessage component to display validation messages for each property. Validation Summary displays summary of all validation messages

Add the below code in AddEmployeeDialog.cs 

  • This is component class which would invoke EmployeeDataservice
  • Employee Data service would call .NET Core API
using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Threading.Tasks;  
using EmployeePortal.Shared;  
using EmployeePortal.Client.Services;  
using Microsoft.AspNetCore.Components;  
namespace EmployeePortal.Client.Components {  
    public partial class AddEmployeeDialog: ComponentBase {  
        public Employee Employee {  
            get;  
            set;  
        } = new Employee {};  
        [Inject]  
        public IEmployeeDataService EmployeeDataService {  
            get;  
            set;  
        }  
        public bool ShowDialog {  
            get;  
            set;  
        }  
        [Parameter]  
        public EventCallback <bool> CloseEventCallback {  
            get;  
            set;  
        }  
        public void Show() {  
            ResetDialog();  
            ShowDialog = true;  
            StateHasChanged();  
        }  
        public void Close() {  
            ShowDialog = false;  
            StateHasChanged();  
        }  
        private void ResetDialog() {  
            Employee = new Employee {};  
        }  
        protected async Task HandleValidSubmit() {  
            await EmployeeDataService.AddEmployee(Employee);  
            ShowDialog = false;  
            await CloseEventCallback.InvokeAsync(true);  
            StateHasChanged();  
        }  
    }  
}  

Based on ShowDialog property pop up would be toggle hide/show.

Implement the service: Implement the service and register it with the dependency injection container. In Blazor, dependency injection is used to manage the lifecycle of services and provide them to components or other services when needed.

  • Define the service interface: Create an interface that defines the contract for the service you want to inject.
  • Implement the service: Implement the service and register it with the dependency injection container.
  • Register the service: In the Program.cs file, register the service with the dependency injection container using the services collection.
  • Inject the service: In a component or other service, inject the service using the @inject directive.

Employee model

using System;  
using System.ComponentModel.DataAnnotations;  
using System.ComponentModel.DataAnnotations.Schema;  
namespace EmployeePortal.Shared {  
    [Table("Employee")]  
    public partial class Employee {  
        public int EmployeeId {  
            get;  
            set;  
        }  
        [Required]  
        [StringLength(50, ErrorMessage = "First name is too long.")]  
        public string FirstName {  
            get;  
            set;  
        }  
        [Required]  
        [StringLength(50, ErrorMessage = "Last name is too long.")]  
        public string LastName {  
            get;  
            set;  
        }  
        [Required]  
        [EmailAddress]  
        public string Email {  
            get;  
            set;  
        }  
        public string Street {  
            get;  
            set;  
        }  
        public string Zip {  
            get;  
            set;  
        }  
        public string City {  
            get;  
            set;  
        }  
        public string PhoneNumber {  
            get;  
            set;  
        }  
        [StringLength(1000, ErrorMessage = "Comment length can't exceed 1000 characters.")]  
        public string Comment {  
            get;  
            set;  
        }  
    }  
}  

Validate modal data and save using Data service and .NET Core API

Create a new Service Folder and Add new Employee Service

builder.Services.AddHttpClient<IEmployeeDataService, EmployeeDataService>(client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)); 

Data Service would have AddEmployee function as below which would call the .NET Core API

public async Task < Employee > AddEmployee(Employee employee) {  
    var employeeJson = new StringContent(JsonSerializer.Serialize(employee), Encoding.UTF8, "application/json");  
    var response = await _httpClient.PostAsync($ "api/employee", employeeJson);  
    if (response.IsSuccessStatusCode) {  
        return await JsonSerializer.DeserializeAsync < Employee > (await response.Content.ReadAsStreamAsync());  
    }  
    return null;  
}  

In .NET Core Project create a new API controller as below

[Route("api/employee")]  
[HttpPost]  
public IActionResult CreateEmployee([FromBody] Employee employee) {  
    if (employee == null) return BadRequest();  
    if (employee.FirstName == string.Empty || employee.LastName == string.Empty) {  
        ModelState.AddModelError("Name/FirstName", "The name or first name shouldn't be empty");  
    }  
    if (!ModelState.IsValid) return BadRequest(ModelState);  
    var createdEmployee = _employeeRepository.AddEmployee(employee);  
    return Created("employee", createdEmployee);  
}  

Register Repository in Startup.cs

services.AddScoped<IEmployeeRepository, EmployeeRepository>();  

Repository to save data in database

public Employee AddEmployee(Employee employee) {  
    var addedEntity = _appDbContext.Employees.Add(employee);  
    _appDbContext.SaveChanges();  
    return addedEntity.Entity;  
}  

How to use modal custom component on home page

Create a new razor page Employee and import component using this syntax

@page"/"  
@using EmployeePortal.Client.Components;  
<button@onclick="QuickAddEmployee"class="btn btn-dark table-btn quick-add-btn">  +  </button>  
<AddEmployeeDialog @ref="AddEmployeeDialog"></AddEmployeeDialog>  

@ref is a built-in directive in Blazor that allows you to create a reference to a component.

Employee Page class file.

Inherit it from component base .StateHasChanged is a method in Blazor that is used to trigger a re-rendering of a component and its child components. Whenever there is a change in the state of a component that requires the UI to be updated, the StateHasChanged method needs to be called.

public partial class EmployeePage:ComponentBase
    {
        public IEnumerable<EmployeePortal.Shared.Employee> Employees { get; set; }

        [Inject]
        public IEmployeeDataService EmployeeDataService { get; set; }

        [Inject]
        public ToastService ToastService { get; set; }

        public AddEmployeeDialog AddEmployeeDialog { get; set; }

        protected async override Task OnInitializedAsync()
        {

          Employees = (await EmployeeDataService.GetAllEmployees()).ToList();
            if (Employees != null)
            {
                ToastService.ShowToast("Employee data loaded", ToastLevel.Info);
            }

        }

        protected void QuickAddEmployee()
        {
            AddEmployeeDialog.Show();
        }


        public async void AddEmployeeDialog_OnDialogClose()
        {
            Employees = (await EmployeeDataService.GetAllEmployees()).ToList();
            StateHasChanged();
        }

    }

Run the application locally and click on Add Employee. Add new employee modal pop up would be displayed. If user tries to submit blank form validation messages would be display.

Scroll to Top