How to two-way data binding of radio button input with Blazor ?
Table of Contents
The two techniques that we're going to look at are.
use standard HTML form elements
Multi-Select Checkbox Dropdown List(.Net 5.x)
Multi-Select Checkbox Dropdown List(.Net 3.x)
use EditForm component
.Net 6.x
.Net 6.x- <InputSelect> as a multi-select
.Net 5.x
.Net 5.x -InputRadioGroup
1. Use standard HTML form elements
.net 5.x
Multi-Select Checkbox Dropdown List(.Net 5.x)
https://findandsolve.com/articles/multiselect-dropdownlist-in-asp-dot-net-core-dot-net-5
.net Core 3.1
such as <input> and <select> within our mark-up
select Event handlers
select add @onchange Event handlers
<div class="row" style="padding-top:10px">
<div class="col-md-4">
<select class="form-control" @onchange="((e)=>CountryClicked(e))">
<option value="">-- 请选择板块 --</option>
@foreach (var item in countryList)
{
<option value="@item.DomainName">@item.DomainName</option>
}
</select>
</div>
<div class="col-md-4">
<select class="form-control" @onchange="((e)=>CityClicked(e))">
<option value="">-- 请选择子板块 --</option>
@if (cityList != null)
{
@foreach (var city in cityList)
{
<option value="@city.DomainName">@city.DomainName</option>
}
}
</select>
</div>
@cityList.Count
</div>
@code {
List<Stockso.Core.Domain.Stocks.Domain> countryList;
List<Stockso.Core.Domain.Stocks.SubDomain> cityList;
Stockso.Core.Domain.Stocks.SubDomain cityCode;
string countryId { get; set; }
string countryName { get; set; }
string cityId { get; set; }
string cityName { get; set; }
Stockso.Core.Domain.Stocks.Domain[] stockBlockList;
Stockso.Core.Domain.Stocks.Domain[] forecasts;
protected override async Task OnInitializedAsync()
{
countryList = await Http.GetJsonAsync<List<Stockso.Core.Domain.Stocks.Domain>>("http://api.stockso.com/v1/StockFullABK/GetMainFullABK");
//初始化变量
cityList = new List<Stockso.Core.Domain.Stocks.SubDomain>();
cityCode = new Stockso.Core.Domain.Stocks.SubDomain();
// forecasts = await Http.GetJsonAsync<Stockso.Core.Domain.Stocks.Domain[]>("http://api.stockso.com/v1/GetStockInfo/GetFullABK");
// forecasts = await Http.GetJsonAsync<Stockso.Core.Domain.Stocks.Domain[]>("http://api.stockso.com/v1/GetStockInfo/GetFullABK");
}
protected async Task CountryClicked(ChangeEventArgs countryEvent)
{
cityList.Clear();
cityName = string.Empty;
countryId = countryEvent.Value.ToString();
countryName = countryList.FirstOrDefault(s => s.DomainName == countryId).DomainName;
cityList = await Http.GetJsonAsync<List<Stockso.Core.Domain.Stocks.SubDomain>>("http://api.stockso.com/v1/StockFullABK/GetSubFullABKList/" + countryId);
this.StateHasChanged();
}
protected async void CityClicked(ChangeEventArgs cityEvent)
{
cityId = cityEvent.Value.ToString();
cityCode = await Http.GetJsonAsync<Stockso.Core.Domain.Stocks.SubDomain>("http://api.stockso.com/v1/StockFullABK/GetSubFullABK/" + cityId);
this.StateHasChanged();
}
}
2.The following component shows an example of how to perform the initial redirection when the user selects a culture:
razor
@inject NavigationManager NavigationManager
<h3>Select your language</h3>
<select @onchange="OnSelected">
<option>Select...</option>
<option value="en-US">English</option>
<option value="fr-FR">Français</option>
</select>
@code {
private double textNumber;
private void OnSelected(ChangeEventArgs e)
{
var culture = (string)e.Value;
var uri = new Uri(NavigationManager.Uri())
.GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);
var query = $"?culture={Uri.EscapeDataString(culture)}&" +
$"redirectUri={Uri.EscapeDataString(uri)}";
NavigationManager.NavigateTo("/Culture/SetCulture" + query, forceLoad: true);
}
}
select
<!--显示提示信息,数据来自Description字段-->
<select class="form-control" @bind="searchModel.SelectedMenuId">
@foreach (var item in searchModel.AvailablePanKouDataMenu)
{
<option [email protected]>@item.Description</option>
}
</select>
绑定查询model
<!--双向绑定数据search-->
<form>
<label>上市日期</label>
<div class="form-row">
<div class="form-group col-md-6">
<label>From</label>
<input class="form-control" @bind="stockInfoSearchModel.StockTradeFirstDayDateRange.From" format-value="yyyy/MM/dd" aria-describedby="priceRangeFromHelp" placeholder="输入要查询最小日期" />
</div>
<div class="form-group col-md-6">
<label>to</label>
<input class="form-control" @bind="stockInfoSearchModel.StockTradeFirstDayDateRange.To" format-value="yyyy/MM/dd" aria-describedby="priceRangeToHelp" placeholder="输入要查询最大日期" />
</div>
</div>
<div class="form-group">
<div class="form-check">
<input class="form-check-input" type="checkbox" @bind="stockInfoSearchModel.StockTradeFirstDayDateRange.IsEnabled" aria-describedby="priceRangeFromHelp" placeholder="是否查询日期" />
<label class="form-check-label">
按上市日期查询
</label>
</div>
</div>
</form>
查询事件
@code {
List<StockInfo> forecasts;
[Parameter]
public StockInfoSearchModel stockInfoSearchModel { get; set; }
protected override async Task OnInitializedAsync()
{
//股票信息查询菜单
stockInfoSearchModel = await StockDataDatabaseService.GetStockInfoSearchViewMode();
}
//查询按钮
protected override async Task OnParametersSetAsync()
{
indexCount = 0;
stockInfoSearchModel.CurrentPage = 0;
forecasts = await StockDataDatabaseService.GetStockInfo(stockInfoSearchModel);
}
}
multi checkbox
<form method="post">
@for (var i = 1; i <= 10; i++)
{
<input name="AreChecked" type="checkbox" value="@i" /> @i<br />
}
<button>Click</button>
</form>
When you select multiple boxes and submit the form, the values are included in the request like this:
AreChecked=1&AreChecked=2&AreChecked=4&AreChecked=6&AreChecked=10
https://www.learnrazorpages.com/razor-pages/forms/checkboxes
<ul>
@foreach (var todo in todos)
{
<li>
<input type="checkbox" @bind="todo.IsDone" />
<input @bind="todo.Title" />
</li>
}
</ul>
two-way data binding of radio button
@functions {
int EditionCode = 1;
// "Edition" class has "int Code" and "string Text" properties.
Edition[] Editions = new [] {
new Edition { Code = 1, Text = "Home" },
new Edition { Code = 2, Text = "Pro" },
new Edition { Code = 3, Text = "Enterprise" },
};
}
@foreach (var edition in this.Editions)
{
<label>
<input type="radio"
name="edition"
checked="@(EditionCode == edition.Code)"
onchange="@(() => EditionCode = edition.Code)"/>
@edition.Text
</label>
}
Multi-Select Checkbox Dropdown List(.Net 3.x)
2.Use EditForm component
There is a standard collection of input components available in Blazor, all descended from the base class InputBase<T>.
.Net 8.x
Form.razor
@using WireGuardUI.Models
<h1>New Client Form</h1>
<EditForm Model="@dev" OnValidSubmit="@OnValidSubmit">
<DataAnnotationsValidator />
<ValidationSummary />
555
@dev.Peer.AllowedIPs
<div class="form-group ">
<div>
<label>数量 :</label>
<div>
<InputText @bind-Value="@dev.Interface.PrivateKey" />
<ValidationMessage For="@(() => dev.Interface.PrivateKey)" />
</div>
</div>
</div>
<button type="submit" class="btn btn-success">
@ButtonText
</button>
</EditForm>
@code {
public List<WireGuardClient> developers = new List<WireGuardClient>();
[Parameter] public WireGuardClient dev { get; set; }
[Parameter] public string ButtonText { get; set; } = "Save";
[Parameter] public EventCallback OnValidSubmit { get; set; }
private void HandleValidSubmit()
{
// Save the data
}
}
how to use
传递ButtonText="Create Developer" dev="@dev" 2个参数到Form.razor
@page "/WireGuardClients/Create"
@using Microsoft.AspNetCore.Authorization
@using WireGuardUI.Models
@inject ILogger<Create> Logger;
@*
@attribute [Authorize(Roles = "Administrator")] *@
@inject NavigationManager uriHelper
<h3>Create</h3>
<Form ButtonText="Create Developer" dev="@dev"
OnValidSubmit="@CreateDeveloper" />
@code {
WireGuardClient dev = new WireGuardClient();
//点击提交后,执行如下代码
async Task CreateDeveloper()
{
// await http.PostAsJsonAsync(GlobalHelper.BaseUrl + "/api/Employee", dev);
uriHelper.NavigateTo("/Pages/WireGuardClients/List");
}
}
.Net 6.x
Multi-Select Support
In version .Net 6 when a <InputSelect> component is bound to an IEnumerable<T> it is rendered as a multi-select, thus enabling the user to select multiple values.
Here’s a Blazor EditForm in action.
<EditForm Model="Command" OnValidSubmit="HandleValidSubmit">
<label for="title">Title</label>
<InputText id="title" @bind-Value="Command.Title" class="form-control"/>
<label for="slug">Slug</label>
<InputText id="slug" @bind-Value="Command.Slug" class="form-control"/>
<InputTextArea @bind-Value="Command.Body" class="form-control" rows="20"/>
<button type="submit" class="btn btn-primary">Publish</button>
</EditForm>
you’ll get a pretty standard looking form
<form>
<label for="title">Title</label>
<input id="title" class="valid">
<label for="slug">Slug</label>
<input id="slug" class="valid">
<textarea rows="20" class="valid"></textarea>
<button type="submit">Publish</button>
</form>
.Net 5.x
InputRadio
Blazor in .NET 5 now includes built-in InputRadio and InputRadioGroup components. These components simplify data binding to radio button groups with integrated validation alongside the other Blazor form input components.
Opinion about blazor:
<InputRadioGroup @bind-Value="survey.OpinionAboutBlazor">
@foreach (var opinion in opinions)
{
<div class="form-check">
<InputRadio class="form-check-input" id="@opinion.id" Value="@opinion.id" />
<label class="form-check-label" for="@opinion.id">@opinion.label</label>
</div>
}
</InputRadioGroup>
.Net core 3.x
datetime
C# Blazor and data binding to a DateTime
1. date
<input type="date" @bind="StartDate" @bind:format="yyyy-MM-dd">
2.time
<EditForm Model=@model OnValidSubmit="Submit">
<InputText type="time" @bind-Value="TimeProxy" />
</EditForm>
@code {
// This field is required as you can not use property in out statement
private TimeSpan LocalTime = TimeSpan.FromHours(0);
private string TimeProxy {
get => model.Time.ToString();
set => TimeSpan.TryParse(value,out LocalTime);
}
private void Submit() {
model.Time = LocalTime;
// following submit logic...
}
}
3.data and time
<input type="datetime" @bind="searchModel.ReportDateTimeRange.To" @bind:format="yyyy-MM-dd HH:mm:ss">
<InputNumber>
<div class="form-group ">
<div>
<label>数量 :</label>
<div>
<InputNumber @bind-Value="@dev.Quantity" />
<ValidationMessage For="@(() => dev.Quantity)" />
</div>
</div>
</div>
@SendComment for example
<EditForm Model="@comment" OnValidSubmit="@SendComment">
<DataAnnotationsValidator />
<ValidationSummary />
<div class="form-group">
<label for="CommentAuthor">Author</label>
<InputText @bind-Value="comment.Author" class="form-control" id="CommentAuthor" placeholder="Hater" />
</div>
<div class="form-group">
<label for="CommentText">Text</label>
<InputTextArea @bind-Value="comment.Text" class="form-control" id="CommentText" rows="3" />
</div>
<button type="submit" class="btn btn-primary g-recaptcha">Send</button>
</EditForm>
see:
EditForm component
https://blazor-university.com/forms/editing-form-data/