Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Blazor: binding to a MultiSelectList (ideally with a checkbox)

Experimenting with Blazor (Server, if that makes any difference), and I'm having difficulty getting binding to a MultiSelectList to work....

Bit of background: I'm dealing with EF Core and have a Many-to-Many relationship, let's say between people and cars. I'm currently loading a page that shows the existing details, and allowing the user to update this page.

So in my Service, I load my Person entity from the DB, and this includes the details of all the cars they currently own. I also load the list of all the available cars. My Service method then creates a MultiSelectList and adds it to my ViewModel (to be returned to the Razor Page):

Service method

vm.CarSelector = new MultiSelectList(
     allCars,
     nameof(Car.CarId), 
     nameof(Car.Name), 
     person.OwnedCars.Select(oc => oc.CarId));

This is fictitious code, but I hope you get the picture. When debugging this (in the Service method) I can see that this MultiSelectList has an entry for every car, and the ones that are already selected are showing as Selected. Great!

Blazor Razor Page

So, this is where I come unstuck.... I can't work out how to do the two-way data-binding of a Razor control to this object.

  • I'm trying to use an <InputSelect />, but that might not be the best control to use.
  • ideally (actually, that's more of a "must have"), each option should have CheckBox.
  • I'm wondering whether the use of a MultiSelectList really buys me anything
like image 684
DrGriff Avatar asked Oct 10 '19 16:10

DrGriff


People also ask

How to create checkboxlist in Blazor?

Open the BlazorComponents Project, right click on the Shared folder and select Option Add => Razor Component like below screenshot. On selecting that option you will get the following screen, give the name of the component as CheckBoxList as shown in the screenshot.

What is the Blazor multiselect component?

The Blazor MultiSelect Component displays to users a list of predefined options and allows typing or multiple selection of values from that list. The MultiSelect is a powerful full-featured UI control that can be bound to data and adapted to fulfill any project requirement by configuring its dimensions, templates and handling the available events.

How do I use two-way binding in Blazor?

To fix this, we need to tell Blazor that the consuming page wants to use two-way binding. Instead of simply setting the CurrentCounterValue we now tell Blazor to bind (i.e. two-way bind) to the value instead. To use two-way binding on a parameter simply prefix the HTML attribute with the text @bind-.

How do I bind a Boolean to a checkbox in HTML?

Instead, use the @bind syntax for checkboxes, which is much more robust and will work both ways (changing the bound boolean value from code & interacting with the checkbox on the UI). See the syntax below: The bind attribute will automatically bind your boolean value to the "checked" property of the html element.


1 Answers

Checkboxes are a bit different in blazor. Normally you would use the bind-value attribute on an input element as shown below, however, this is not recommended as you will only be able to read the value and NOT update the UI by changing the boolean value via code:

    <input type="checkbox" @bind-value="@item.Selected"/>

Instead, use the @bind syntax for checkboxes, which is much more robust and will work both ways (changing the bound boolean value from code & interacting with the checkbox on the UI). See the syntax below:

    <input type="checkbox" @bind="@item.Selected"/>

The bind attribute will automatically bind your boolean value to the "checked" property of the html element.

Also make sure you are binding to the "Selected" property rather than the "Value" property.

Using the built in bind will prevent the need to manually setup events as you did in your answer. You can also get rid of the if/else block and merge your code into a single code flow since you are now binding to the boolean rather than setting the checked property manually. If you still need to tap into an event to fire off some process(maybe hiding parts of UI on checking a box), I'd suggest using the onclick event and manually passing in the multiselect Item for each line. Here is the final code:

@foreach(var item in list)
{
    <input type="checkbox" @bind="item.Selected" @onclick="(()=>handleClick(item))" />
}
@foreach(var item in list.Where(x=>x.Selected))
{
    <p> Item @item.Text is Selected</p>
}

@code {
    MultiSelectList list = new MultiSelectList(new List<Car> { new Car { Year = 2019, Make = "Honda", Model = "Accord" }, new Car { Make = "Honda", Model = "Civic", Year = 2019 } });

    private void handleClick(SelectListItem item)
    {        
        //Do something crazy
    }

}
like image 158
Eric Holland Avatar answered Sep 28 '22 04:09

Eric Holland