1

In my Blazor Webassembly (client-side) 3.2.0 application, I have a lot of the following select elements on a page, which create a combo box listing available items of an enum:

<select @bind="SomeEnumValue">
    @foreach (var element in Enum.GetValues(typeof(SomeEnum)))
    {
        <option value="@element">@element</option>
    }
</select>

While this works, I want to prevent repeating myself over and over for every such combo box, and thought of creating the following EnumSelect component:

@typeparam T
<select @bind="Value">
    @foreach (var element in Enum.GetValues(typeof(@T)))
    {
        <option value="@element">@element</option>
    }
</select>

@code {
    [Parameter]
    public T Value { get; set; } = default(T)!;

    [Parameter]
    public EventCallback<T> ValueChanged { get; set; }
}

And then use it like this:

<EnumSelect T="SomeEnum" @bind-Value="SomeEnumValue" />

However, while the display of the SomeEnumValue property and enum items works, the property is not written back to upon selecting another item from the combo box.

I'm not sure why this doesn't work. I kinda suspect the EnumSelect component storing its own copy of that value, not writing it back, but I thought the binding solves this for me.

Is there any (easier) way to get this combo box component working? Where is my mistake (in understanding bindings)?

Ray
  • 7,940
  • 7
  • 58
  • 90

1 Answers1

1

Found my answer by rewording my question a bit (sorry, not yet used to all the Blazor terminology): Blazor TwoWay Binding on custom Component

In case of my problem, the final working component looks like this: The check if the value actually changed inside the property was required, or I hung my app (possibly because it wanted to set it over and over again?):

@typeparam T
<select @bind="Value">
    @foreach (var element in Enum.GetValues(typeof(@T)))
    {
        <option value="@element">@element</option>
    }
</select>

@code {
    private T _value = default(T)!;

    [Parameter]
    public T Value
    {
        get => _value;
        set
        {
            if (_value.Equals(value))
                return;

            _value = value;
            ValueChanged.InvokeAsync(_value);
        }
    }

    [Parameter]
    public EventCallback<T> ValueChanged { get; set; }
}
Ray
  • 7,940
  • 7
  • 58
  • 90