GeeksGoneBad
GeeksGoneBad

Reputation: 70

Blazor InputCheckbox binding to string backing field

I am trying to make a dynamic form system and I want to be able to bind an InputCheckbox to a database field that's a string rather than a bool...

   <EditForm Model="@theEntryResults" OnValidSubmit="@SaveEntries">
        <div class="row">
            <div class="col-6">
                @foreach (var entry in theEntryResults)
                {
                    <div class="form-group m-2">
                        <label>
                            @entry.Field.FieldName:
                            @switch (entry.Field.FieldTypeID)
                            {
                                case 0:
                                    <InputText @bind-Value="@entry.Value" class="form-control"></InputText>
                                    break;
                                case 1:
                                    <InputSelect @bind-Value="@entry.Value" class="form-select">
                                        <option value=""></option>
                                        @foreach (var option in entry.Field.Choices)
                                        {
                                            <option value="@option.Value">@option.Name</option>
                                        }
                                    </InputSelect>
                                    break;
                                case 2:
                                    <InputCheckbox @bind-Value="@MyValue" class="form-check-inline" style="width: 50px; height: 50px;"></InputCheckbox>
                                    break;
                            }

                        </label>
                    </div>
                }
            </div>
        </div>
        <button class="btn btn-success" type="submit">Save</button>
    </EditForm>

is what I am trying but entry.Value is a string and so this is giving me "Cannot convert string to bool"

Any ideas?

Thanks!

Upvotes: 0

Views: 1608

Answers (2)

Ibrahim Timimi
Ibrahim Timimi

Reputation: 3710

An example to bind string to an InputCheckbox would be by using a component where the string can be converted to boolean and bind to InputCheckBox and vice versa.

Component:

@* MyInputCheckBox.razor *@
<InputCheckbox @bind-Value="isCheck"
               class="form-check-inline"
               style="width: 50px; height: 50px;"/>

@code {
    [Parameter]
    public string CheckValueStr { get; set; }
    
    [Parameter]
    public EventCallback<string> CheckValueStrChanged { get; set; }
    
    private bool _isCheck;
    public bool isCheck
    {
        get { return _isCheck; }
        set { 
            _isCheck = value;
            CheckValueStrChanged.InvokeAsync(value.ToString());}
    }
    
    protected override void OnInitialized()
    {
        isCheck = bool.Parse(CheckValueStr);
    }
}

Page:

@page "/"
@using BlazorApp2.Components

<EditForm Model="sample">
    <MyInputCheckBox @bind-CheckValueStr="@sample.CheckValue" />
</EditForm>

<br/>
@sample.CheckValue

@code {
    private Sample sample = new Sample();

    public class Sample
    {
        public string CheckValue = "false";
    }
}

Output:

Output

Upvotes: 0

Neil W
Neil W

Reputation: 9162

Bind it to a bool in your code section of the component and then translate in the getters and setters of that.

<InputCheckbox @bind-Value=@MyValue />
    
@code {

    bool MyValue
    {
        get => Convert.ToBoolean(entry.Value);
        set => entry.Value = value.ToString();
    }
}

As you are using a for each loop, my recommendation would be to use a child-component for each entry (e.g. EntryViewComponent), so that each child-component is focused on working with an individual entry. In this way, the above suggestion would still apply.

@foreach (var entry in theEntryResults)
{
    <EntryViewComponent Entry=@entry />
}

EntryViewComponent

<markup that was previously in the for-each loop>

@code {
    [Parameter] public EntryClass Entry { get; set; }

    // similar code to first suggestion above
}

If you wish to continue using mark-up inside the for each loop instead of a component, the following may work:

<InputCheckbox Value=@(Convert.ToBoolean(entry.Value))
               ValueChanged=@((v) => entry.Value = v.ToString()) />

In this code, instead of auto-binding, you are using different code for the setting of the value of the checkbox and the handling of a value change from the checkbox.

Upvotes: 1

Related Questions