Search code examples
c#blazor

Convert a value to int from string in @bind-Value in Blazor


In my Blazor page, I have this simple code (ToggleButtonGroup is from here).

<div class="col-lg-6">
    <label class="form-label form-field-label">Insert your value</label>
    <ToggleButtonGroup Options="@GroupOptions.Options0To10" 
        @bind-Value="@_session.InteractiveNumber" />
    <hr>
</div>

The model I use is defined like that

public class Session {
    public int ActiveNumber { get; set; }
}

public Session _session = new();

The ToggleButtonGroup returns a string as a value but I want to store in the database and this is why the Session is defined like that. How can I cast the value from a string to int? Can I use something like @(e => _session.ActiveNumber = e.ToString())?


Solution

  • For reference see this answer for the previous question on this topic - Bootstrap radio button group

    You need to make ToggleButtonGroup generic. I've modified the code from the original answer:

    @using System.Diagnostics.CodeAnalysis
    @typeparam TValue
    @inherits InputBase<TValue>
    
    <div class="btn-group mt-1 me-2 mb-3" data-toggle="buttons">
        @foreach (var item in this.Options)
        {
            <button type="button" class="@this.GetButtonCSS(item.Value)" @onclick="() => ValueHasChanged(item.Value)">
                @item.Label
            </button>
        }
    </div>
    
    @code {
        [Parameter, EditorRequired] public IEnumerable<SelectOption<TValue>> Options { get; set; } = Enumerable.Empty<SelectOption<TValue>>();
        [Parameter] public string SelectedCss { get; set; } = "btn btn-primary";
        [Parameter] public string UnSelectedCss { get; set; } = "btn btn-outline-primary";
    
        // We must implement as it's abstract in InputBase.
        // But not used as we bypass the string conversion logic by setting CurrentValue directly
        protected override bool TryParseValueFromString(string? value, [MaybeNullWhen(false)] out TValue result, [NotNullWhen(false)] out string? validationErrorMessage)
        {
            result = this.CurrentValue!;
            validationErrorMessage = null;
            return true;
        }
    
        private string GetButtonCSS(TValue value)
        {
            return value?.Equals(this.Value) ?? false
                ? this.SelectedCss
                : this.UnSelectedCss;
        }
    
        private void ValueHasChanged(TValue value)
        {
            // Bypass all the string conversion stuff as we have the value
            // Set CurrentValue directly instead of CurrentValueAsString and using the built in string to TValue conversion logic
            this.CurrentValue = value;
        }
    }
    
    public readonly record struct SelectOption<TValue>(TValue Value, string Label);
    

    And Demo page:

    @page "/"
    
    <PageTitle>Home</PageTitle>
    
    <h1>Hello, world!</h1>
    
    Welcome to your new app.
    
    <EditForm Model="_model">
        <ToggleButtonGroup Options="_options" @bind-Value="_model.Value1" />
        <ToggleButtonGroup Options="_intOptions" @bind-Value="_model.Value2" />
        <ToggleButtonGroup Options="_boolOptions" @bind-Value="_model.Value3" />
    </EditForm>
    
    <div class="bg-dark text-white m-2 p-2">
        <pre>Value1: @_model.Value1</pre>
        <pre>Value2: @_model.Value2</pre>
        <pre>Value3: @_model.Value3</pre>
    </div>
    
    @code {
        private List<SelectOption<string>> _options = new() {
            new("Yes", "Yes"),
            new("No", "No"),
            new("Sometimes", "Sometimes")
        };
    
        private List<SelectOption<int>> _intOptions = new() {
            new(1, "Yes"),
            new(0, "No"),
            new(-1, "Sometimes")
        };
    
        private List<SelectOption<bool>> _boolOptions = new() {
            new(true, "On"),
            new(false, "Off")
        };
    
        private Model _model = new();
    
        public class Model
        {
            public string Value1 { get; set; } = "N";
            public int Value2 { get; set; }
            public bool Value3 { get; set; }
        }
    }
    

    enter image description here