ASP.NET Core Blazor | Dropdownlist Data from Database
This is Part 19 of Web development with Blazor video series. In this video we will discuss how to bind data from a database table to a dropdownlist in ASP.NET Core Blazor. Another common usecase is to bind an Enum to dropdownlist, so we will discuss binding an enum as well.
In our next video we will discuss how to perform Insert, Update and Delete operations in datagrid. A DropDownList is usually the preferred choice for Gender
and Department
when we add a new employee or edit an existing employee. Gender is an enum and the list of departments come from a database table.
Enable DataGrid CRUD operations
We will be using Syncfusion DataGrid to perform the CRUD operations. We discussed the basics of DataGrid and setting it up from scratch in Part 4 of this video series.
- For the DataGrid to be able to perform CRUD operations it needs to know the primary key column.
- To specify the primary key, set
IsPrimaryKey
property totrue
. - In this example,
EmployeeId
column is marked as the primary key. - On
<GridEditSettings>
component, setAllowAdding="true"
,AllowEditing="true"
andAllowDeleting="true"
.
@page "/gridedit"
@using Syncfusion.Blazor.Grids
<div style="width:750px">
<SfGrid DataSource="@Employees" AllowPaging="true"
Toolbar="@(new List<string>() { "Add", "Edit", "Update", "Delete", "Cancel" })">
<GridEditSettings AllowAdding="true" AllowEditing="true" AllowDeleting="true">
</GridEditSettings>
<GridPageSettings PageSize="5"></GridPageSettings>
<GridColumns>
<GridColumn IsPrimaryKey="true" Field=@nameof(Employee.EmployeeId) HeaderText="ID"
Width="40px"></GridColumn>
<GridColumn Field=@nameof(Employee.FirstName) HeaderText="First Name"></GridColumn>
<GridColumn Field=@nameof(Employee.LastName) HeaderText=" Last Name"></GridColumn>
<GridColumn Field=@nameof(Employee.DateOfBrith) Format="d"
HeaderText="Date of Birth"></GridColumn>
<GridColumn Field="Department.DepartmentName" HeaderText="Department" Width="140px">
</GridColumn>
<GridColumn Field=@nameof(Employee.Gender) HeaderText="Gender"
Width="140px"></GridColumn>
<GridColumn Field=@nameof(Employee.Email) HeaderText="Email"></GridColumn>
</GridColumns>
</SfGrid>
</div>
@code{
public List<Employee> Employees { get; set; }
[Inject]
public IEmployeeService EmployeeService { get; set; }
protected override async Task OnInitializedAsync()
{
Employees = (await EmployeeService.GetAllEmployees()).ToList();
}
}
Binding complex nested properties to datagrid columns
- To display employee department name in the datagrid we might do something like the following.
Department
is a complex object.- The following code complies but at runtime we get a null reference exception.
<GridColumn Field=@nameof(Employee.Department.DepartmentName) HeaderText="Department">
</GridColumn>
To bind a complex property such as a Department
to a DataGrid column use the following syntax.
<GridColumn Field="Department.DepartmentName" HeaderText="Department">
</GridColumn>
Please note : If you do not see the department name displayed in the Datagrid, in the EmployeeRepository
check if the Department
is being loaded along with the Employee
object.
public class EmployeeRepository : IEmployeeRepository
{
private readonly AppDbContext appDbContext;
public EmployeeRepository(AppDbContext appDbContext)
{
this.appDbContext = appDbContext;
}
public async Task<IEnumerable<Employee>> GetAllEmployees()
{
return await appDbContext.Employees.Include(e => e.Department).ToListAsync();
}
}
Blazor DataGrid Toolbar
Set Toolbar
property on the datagrid to display the toolbar icons (Add, Edit, Update, Delete and Cancel)
<SfGrid DataSource="@Employees" AllowPaging="true"
Toolbar="@(new List<string>() { "Add", "Edit", "Update", "Delete", "Cancel" })">
- You can edit a row either by double-clicking on the row or by selecting the row and then click on the
Edit
button in the toolbar. - To add a new record click on the
Add
button in the toolbar. - To Save and Cancel use the the respective buttons in the toolbar.
By default a textbox is provided as the interface for Department
and Gender
columns when adding or editing an employee record.
Binding Database data to dropdownlist
Include Syncfusion.Blazor.DropDowns
using declaration
@page "/gridedit"
@using Syncfusion.Blazor.Grids
@using Syncfusion.Blazor.DropDowns
<div style="width:750px">
<SfGrid DataSource="@Employees" AllowPaging="true"
Toolbar="@(new List<string>() { "Add", "Edit", "Update", "Delete", "Cancel" })">
<GridEditSettings AllowAdding="true" AllowEditing="true" AllowDeleting="true">
</GridEditSettings>
<GridPageSettings PageSize="5"></GridPageSettings>
<GridColumns>
<GridColumn IsPrimaryKey="true" Field=@nameof(Employee.EmployeeId) HeaderText="ID"
Width="40px"></GridColumn>
<GridColumn Field=@nameof(Employee.FirstName) HeaderText="First Name"></GridColumn>
<GridColumn Field=@nameof(Employee.LastName) HeaderText=" Last Name"></GridColumn>
<GridColumn Field=@nameof(Employee.DateOfBrith) Format="d"
HeaderText="Date of Birth"></GridColumn>
<GridColumn Field="Department.DepartmentName" HeaderText="Department" Width="140px">
<EditTemplate>
<SfDropDownList TItem="Department" TValue="int" DataSource="@Departments"
@bind-Value="@((context as Employee).DepartmentId)" >
<DropDownListFieldSettings Text="DepartmentName" Value="DepartmentId">
</DropDownListFieldSettings>
</SfDropDownList>
</EditTemplate>
</GridColumn>
<GridColumn Field=@nameof(Employee.Gender) HeaderText="Gender"
Width="140px"></GridColumn>
<GridColumn Field=@nameof(Employee.Email) HeaderText="Email"></GridColumn>
</GridColumns>
</SfGrid>
</div>
@code{
public List<Employee> Employees { get; set; }
public List<Department> Departments { get; set; }
[Inject]
public IEmployeeService EmployeeService { get; set; }
[Inject]
public IDepartmentService DepartmentService { get; set; }
protected override async Task OnInitializedAsync()
{
Employees = (await EmployeeService.GetAllEmployees()).ToList();
Departments = (await DepartmentService.GetAllDepartments()).ToList();
}
}
The following is the HTML specific to the DropDownList
- Include
<SfDropDownList>
inside<EditTemplate>
. Departments
property is the DataSource for the dropdownlist.Departments
property is populated with data by theDepartmentService
.
<GridColumn Field="Department.DepartmentName" HeaderText="Department" Width="140px">
<EditTemplate>
<SfDropDownList TItem="Department" TValue="int" DataSource="@Departments"
@bind-Value="@((context as Employee).DepartmentId)" >
<DropDownListFieldSettings Text="DepartmentName" Value="DepartmentId">
</DropDownListFieldSettings>
</SfDropDownList>
</EditTemplate>
</GridColumn>
IDepartmentService
public interface IDepartmentService
{
Task<IEnumerable<Department>> GetAllDepartments();
Task<Department> GetDepartment(int departmentId);
}
DepartmentService
public class DepartmentService : IDepartmentService
{
private readonly HttpClient httpClient;
public DepartmentService(HttpClient httpClient)
{
this.httpClient = httpClient;
}
public async Task<IEnumerable<Department>> GetAllDepartments()
{
return await httpClient
.GetFromJsonAsync<IEnumerable<Department>>("/api/departments");
}
public async Task<Department> GetDepartment(int departmentId)
{
return await httpClient
.GetFromJsonAsync<Department>($"/api/departments/{departmentId}");
}
}
Register DepartmentService
In the Main()
method in Program.cs
file register DepartmentService
with the dependency injection container.
public class Program
{
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.Services.AddHttpClient<IDepartmentService, DepartmentService>(client =>
{
client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress);
});
await builder.Build().RunAsync();
}
}
Binding enum to dropdownlist
<GridColumn Field=@nameof(Employee.Gender) HeaderText="Gender" Width="140px">
<EditTemplate>
<SfDropDownList ID="Gender" TItem="string" TValue="Gender"
@bind-Value="@((context as Employee).Gender)"
DataSource="@GenderEnumValues">
</SfDropDownList>
</EditTemplate>
</GridColumn>
@code{
public string[] GenderEnumValues = Enum.GetNames(typeof(Gender));
}
© 2020 Pragimtech. All Rights Reserved.