razordata-bindingenumsblazorblazor-server-side

Blazor InputSelect: Unable to Bind Enum Value to Enum Type Using @bind-Value


I am using a Blazor Web App. I have an Enum. It has three values: UpperBody, LowerBody, FullBody. My goal is to have a user select one of these values. Afterwards, the program will take that selected value (UpperBody, LowerBody, FullBody) and filter exercises from a database based on the value. This requires the selected enum value to successfully bind to a variable within my component. I have not found a way to do this. As you'll see in my code, I also have a method that is meant to print the selected enum value to the console. Furthermore (as you'll see), I'm trying to print the value of the Enum within the HTML. This is for debugging so that I can "see" my updated value.

The Enum:

namespace dataBindingProblem
{
    public enum WorkoutType
    {
        UpperBody, LowerBody, FullBody
    }
}

The Component:

NOTE: This code block is missing the EditForm tag. For that reason, upon navigating to the /selectworkout endpoint, you will run into an exception stating that EditContext or Model needs to be used. I'm not sure how to proceed with this as I'm not dealing directly with a Model (Although I did try introducing one as explained below).

@page "/selectworkout"

<h3>Select Workout Type (From Enum Values) </h3>


    <label for="workoutselection"> Select Workout Type </label>
    <InputSelect id="workoutselection" @bind-Value="@selectedWorkoutType" @bind-Value:after="workoutTypeChanged">
        <option value=""> Select Workout Type </option>
        @foreach (var type in Enum.GetValues(typeof(WorkoutType)))
        {
            <option value="@type">@type</option>
        }
    </InputSelect>


<p>Selected Workout Type: @selectedWorkoutType</p>

@code {
    private WorkoutType selectedWorkoutType;

    public void workoutTypeChanged()
    {
        Console.WriteLine($"Workout Type Changed: {selectedWorkoutType}");
    }
}

Things I have tried

In addition to solving the problem, if there are any recommendations to debug something like this in the future, please enlighten me. Bottom line, I just want to get to bind to work. I thought about refactoring the app and removing the enums all together and introducing an in-memory List for the drop-down and ultimately to filter the database, but I don't think its the enums (and their associated models) that are causing the trouble. Thank you.


Solution

  • The simplest way is to introduce a local model. WorkoutType can be null, as it would appear that's what you want [you have a Select Workout Type option].

    Here's some demo code. I've also added some display logic to handle Select Workout Type option so it can't be selected and only shows when the value is null.

    @page "/"
    
    <h3>Select Workout Type (From Enum Values) </h3>
    
    <EditForm Model="_model">
        <label class="form-label"> Select Workout Type </label>
        <InputSelect class="form-select" @bind-Value="@_model.WorkoutType" @bind-Value:after="workoutTypeChanged">
            @if(_model.WorkoutType is null)
            {
                <option disabled="true" selected value=""> Select Workout Type </option>
            }
            @foreach (var type in Enum.GetValues(typeof(WorkoutType)))
            {
                <option value="@type">@type</option>
            }
        </InputSelect>
    </EditForm>
    
    <div class="bg-dark text-white m-2 p-2">
        <pre>Selected Workout Type: @_model.WorkoutType</pre>
    </div>
    
    @code {
        private Model _model = new();
    
        public void workoutTypeChanged()
        {
            Console.WriteLine($"Workout Type Changed: {_model.WorkoutType}");
        }
    
        public enum WorkoutType
        {
            UpperBody, LowerBody, FullBody
        }
    
        private class Model
        {
            public WorkoutType? WorkoutType { get; set; }
        }
    }