1

I have an InputSelect that display various options based on an Enum type, as such

<InputSelect @bind-Value=m_ProjectExtended.EstimateType class="form-control form-control-sm">
    @foreach (var type in @GetEnumValues<EstimateType>())
    {
        <option value="@type.Value">@type.Key</option>
    }
</InputSelect>

public Dictionary<string, int> GetEnumValues<T>()
{
    Dictionary<string, int> values = new Dictionary<string, int>();

    foreach (var enumValue in Enum.GetValues(typeof(T)))
    {
        values.Add(enumValue.GetDisplayAttribute(), (int)enumValue);
    }

    return values;
}

What I'm missing is to be able to have an placeholder option selected by default (ie: "Select the option" when creating a new record for example) and also, being able to reset the InputSelect to this placeholder from the component's code.

The way I do it in Angular is that I add the placeholder option with a value of -1 set the binded field to that value, which does the trick.

Problem is that I don't have a value of -1 in the actual C# enums and don't really want one.

Any way to achieve this ?

Francis Ducharme
  • 4,848
  • 6
  • 43
  • 81
  • Have you tried `m_ProjectExtended.EstimateType = values.First().Value.ToString()`? This will set the first value as default when rendered. – Suprabhat Biswal Jan 25 '21 at 19:25
  • When you talk about a placeholder, you mean a fake select as "--- select a value ---" or a real selected option? – dani herrera Jan 25 '21 at 19:26
  • @daniherrera yes, a "fake", ie: "Select estimate type" – Francis Ducharme Jan 25 '21 at 19:26
  • @FrancisDucharme Why not add a fake option field just before you iterate on Enum to add dynamic options. It's an HTML in the end `` – Suprabhat Biswal Jan 25 '21 at 19:31
  • @SuprabhatBiswal Because the select is binded to `m_ProjectExtended.EstimateType` and it then becomes impossible to clear the selection back to the placeholder. `EstimateType` is an enum. – Francis Ducharme Jan 25 '21 at 19:32
  • I strongly recommend setting object parameters instead of trying to pass around keys and so on. The only place that can't be avoided is in the select itself. Later, when you have a `List`, use a `ComplexCustomClass SelectedItem` property in the same way for easy access to all its members. – Bennyboy1973 Jun 16 '21 at 11:25

2 Answers2

1

You don't need to bind the value, since you aren't forcing a particular selection. Instead, set it in @onchange The title option doesn't need a value, because it never gets hit by onchange. I like to make my SelectedItem nullable, because this works for all enumerables (Lists, Queues etc., not just enums). Setting your selected item to null resets the title option automatically.

<button @onclick="()=> SelectedType=null">Clear</button>
<select @onchange="args => SelectedType = (EstimateType)Enum.Parse(typeof(EstimateType), args.Value.ToString())">
@if (SelectedType is null)
{
    <option selected disabled>Choose an Estimate Type</option>
}
@foreach (var item in Enum.GetNames(typeof(EstimateType)))
{
    <option value="@item">@item</option>
}
</select>
@if(SelectedType is not null)
{
    <div>Selected Estimate Type: @SelectedType.ToString()</div>
}
@code {
    enum EstimateType { Labor, Materials, Drafting, Legal }

    EstimateType? SelectedType { get; set; }
}
Bennyboy1973
  • 3,413
  • 2
  • 11
  • 16
0

If you need to have a "--select a value--" option, this means that your m_ProjectExtended.EstimateType is probably nullable (else it would always have a valid entry for your dropdown).

So to add the functionality, just add the option as suggested but do not bind directly but go trough a property like so:

...

    /* Change binding to local property */
    <InputSelect @bind-Value=EstimateType class="form-control form-control-sm">
        @foreach (var type in @GetEnumValues<EstimateType>())
        {
            <option value="@type.Value">@type.Key</option>
        }
    </InputSelect>

...

@code
{
    public Dictionary<string, int> GetEnumValues<T>()
    {
        Dictionary<string, int> values = new Dictionary<string, int>();

        // Inject placeholder only if there is no value
        if (m_ProjectExtended.EstimateType == null)
        {
            values.Add("--select a value--", -1);
        }
        
        foreach (var enumValue in Enum.GetValues(typeof(T)))
        {
            values.Add(enumValue.GetDisplayAttribute(), (int) enumValue);
        }

        return values;
    }

    // Translate "Nullable" to our extended value with the placeholder
    public int EstimateType
    {
        get => m_ProjectExtended.EstimateType == null ? -1 : (int) m_ProjectExtended.EstimateType;
        set
        {
            if (value > -1)
                m_ProjectExtended.EstimateType = (EstimateType) value;
        }
    }
}

This will display your placeholder only if m_ProjectExtended.EstimateType is not set yet. The Placeholder will vanish automatically once the user selects an option.