Multiple Blazored Typeaheads within foreach
I'm using Blazored Typeahead within my Blazor server application. In my razor page following code
Blazored Typeahead - within Foreach
@foreach (var employee in EmployeeList)
{
<div class="row">
<div class="col-3">
<BlazoredTypeahead SearchMethod="@GetPeopleLocal"
@bind-Value="@SelectedPerson"
placeholder="Search by first name...">
<SelectedTemplate Context="person">
@person.Firstname
</SelectedTemplate>
<ResultTemplate Context="person">
@person.Firstname @person.Lastname
</ResultTemplate>
</BlazoredTypeahead>
</div>
<div class="col-3">
<BlazoredTypeahead SearchMethod="@GetRolesLocal"
@bind-Value="@SelectedRole"
placeholder="Search by role name...">
<SelectedTemplate Context="role">
@role.Rolename
</SelectedTemplate>
<ResultTemplate Context="role">
@role.Rolename
</ResultTemplate>
</BlazoredTypeahead>
</div>
<div class="col-1">
<a href="javascript:void(0)" class="btn btn-danger" @onclick="@(()=>OnEmployeeDelete(employee))">X</a>
</div>
</div>
}
<div class="form-group">
<a href="javascript:void(0)" class="btn btn-success" @onclick="@(()=>OnEmployeeAdd())">Add Employee</a>
</div>
<div class="form-group">
<a href="javascript:void(0)" class="btn btn-success" @onclick="@(()=>CreateEmployeeList())">Create Employee List</a>
</div>
@code {
private List<Employee> EmployeeList = new List<Employee>();
private Employee employee = new Employee();
private List<Person> People = new List<Person>();
private List<Role> Roles = new List<Role>();
private Person SelectedPerson;
private Role SelectedRole;
protected override void OnInitialized()
{
People.AddRange(new List<Person>()
{
new Person() { Id = 1, Firstname = "Martelle", Lastname = "Cullon" },
new Person() { Id = 2, Firstname = "Zelda", Lastname = "Abrahamsson" },
new Person() { Id = 3, Firstname = "Benedetta", Lastname = "Posse" },
new Person() { Id = 4, Firstname = "Benoite", Lastname = "Gobel" },
new Person() { Id = 5, Firstname = "Charlot", Lastname = "Fullicks" },
new Person() { Id = 6, Firstname = "Vinson", Lastname = "Turbat" },
new Person() { Id = 7, Firstname = "Lenore", Lastname = "Malam" },
new Person() { Id = 8, Firstname = "Emanuele", Lastname = "Kolakovic" }
});
Roles.AddRange(new List<Role>()
{
new Role() { Id = 1, Rolename = "Programmer Frontend" },
new Role() { Id = 1, Rolename = "Programmer Backend" },
new Role() { Id = 2, Rolename = "UX Designer" },
new Role() { Id = 3, Rolename = "DBA Developer" }
});
}
private async Task<IEnumerable<Person>> GetPeopleLocal(string searchText)
{
return await Task.FromResult(People.Where(x => x.Firstname.ToLower().Contains(searchText.ToLower())).ToList());
}
private async Task<IEnumerable<Role>> GetRolesLocal(string searchText)
{
return await Task.FromResult(Roles.Where(x => x.Rolename.ToLower().Contains(searchText.ToLower())).ToList());
}
public void OnEmployeeDelete(Employee employee)
{
EmployeeList.Remove(employee);
}
public void OnEmployeeAdd()
{
EmployeeList.Add(new Employee());
}
private async Task CreateEmployeeList()
{
foreach (var employee in EmployeeList)
{
var resultPerson = employee.Person;
var resultRole = employee.Role;
}
}
}
My problem is when I add a new row by clicking "Add Employee" and choose some value for name and role (e.g. Samara and Developer .NET) then all row gets same values. Furthermore when I click the "Create Employee List" button which calls the CreateEmployeeList method then EmployeeList have null values in all rows.
And when trying to delete a row the method OnEmployeeDelete removes the last row, regardless to which row I clicked.
The employee class
public class Employee
{
public Employee() { }
public Employee(Person person, Role role)
{
Person = person;
Role = role;
}
public Person Person { get; set; }
public Role Role { get; set; }
}
The role class
public class Role
{
public Role() { }
public Role(int id, string rolename)
{
Id = id;
Rolename = rolename;
}
public int Id { get; set; }
public string Rolename { get; set; }
}
Note I'm using the repo from Blazor Typeahead: https://github.com/Blazored/Typeahead I have just created a page Foreach.razor and added above code to it.
1 answer
-
answered 2022-05-04 10:43
Yong Shun
From the attached code,
@SelectedPerson
and@SelectedRole
are shared for each element inEmployeeList
. That is why changing@SelectedPerson
or@SelectedRole
in a row will reflect in the other elements.You need a variable to hold the selected employee list.
@foreach (var selectedEmployee in SelectedEmployeeList) { <div class="row"> <div class="col-3"> <BlazoredTypeahead SearchMethod="@GetPeopleLocal" @bind-Value="@selectedEmployee.Person" placeholder="Search by first name..."> <SelectedTemplate Context="person"> @person.Firstname </SelectedTemplate> <ResultTemplate Context="person"> @person.Firstname @person.Lastname </ResultTemplate> </BlazoredTypeahead> </div> <div class="col-3"> <BlazoredTypeahead SearchMethod="@GetRolesLocal" @bind-Value="@selectedEmployee.Role" placeholder="Search by role name..."> <SelectedTemplate Context="role"> @role.Rolename </SelectedTemplate> <ResultTemplate Context="role"> @role.Rolename </ResultTemplate> </BlazoredTypeahead> </div> <div class="col-1"> <a href="javascript:void(0)" class="btn btn-danger" @onclick="@(()=>OnEmployeeDelete(selectedEmployee))">X</a> </div> </div> }
private List<Employee> SelectedEmployeeList = new List<Employee>(); public void OnEmployeeDelete(Employee employee) { SelectedEmployeeList.Remove(employee); } public void OnEmployeeAdd() { SelectedEmployeeList.Add(new Employee()); } private async Task CreateEmployeeList() { foreach (var employee in EmployeeList) { SelectedEmployeeList.Add(new Employee { Person = employee.Person, Role = employee.Role }); } }
do you know?
how many words do you know