[英]How to make two-way binding on Blazor component
我想創建自定義輸入,所以我創建了這個組件:
MyInputComponent.razor
:
<div>
<input type="text" @bind="BindingValue" />
</div>
@code {
[Parameter]
public string BindingValue { get; set; }
}
然后是用法:
<EditForm Model="model" OnValidSubmit="Submit">
<MyInputComponent BindingValue="model.Name" />
</EditForm>
@code {
User model = new User() { Name = "My Name" };
private void Submit()
{
// here I found model.Name = null;
}
}
當我調試MyInputComponent
時,我發現了我輸入的值。 但是當我提交表單時,該值為空。
什么東西少了?
引用Blazor 文檔:
組件參數
綁定識別組件參數,其中@bind-{property} 可以跨組件綁定屬性值。
對於您的頁面:
<EditForm Model="model" OnValidSubmit="Submit">
<MyInputComponent @bind-BindingValue="model.Name" />
</EditForm>
子組件MyInputComponent
:
<div>
<InputText type="text" @bind-Value="@BindingValue" />
</div>
@code {
private string _value;
[Parameter]
public string BindingValue
{
get => _value;
set
{
if (_value == value ) return;
_value = value;
BindingValueChanged.InvokeAsync(value);
}
}
[Parameter]
public EventCallback<string> BindingValueChanged { get; set; }
}
注意
EventCallback<string> BindingValueChanged
從子組件引發綁定更改。BindingValue
和BindingValueChanged
作為標識符,但是,您可以只使用Value
和ValueChanged
。 然后將是: <MyInputComponent @bind-Value="model.Name" />
已編輯:有關干凈的解決方案,請參閱下面的選項 2:
如果您想將您的組件放在 EditForm 中並處理驗證,或使用 onchange 事件采取其他操作,您應該引發EditContext.NotifyFieldChanged
。 您有 2 個選項可以執行此操作。
您可以從CascadeParameter
獲取EditContext
並手動調用NotifyFieldChanged
:
[CascadingParameter] EditContext EditContext { get; set; } = default!;
[Parameter] public Expression<Func<string>>? ValueExpression { get; set; }
#endregion
#region bindedValue
[Parameter] public EventCallback<string> ValueChanged { get; set; }
private string _value { set; get; } = "";
[Parameter]
public string Value
{
get => _value;
set
{
if (_value == value) return;
_value = value;
ValueChanged.InvokeAsync(value);
var fieldIdentifier = FieldIdentifier.Create(ValueExpression);
EditContext.NotifyFieldChanged(fieldIdentifier);
}
}
您可以從InputBase<string>
繼承並只實現TryParseValueFromString
。 InputBase
將為您完成工作,當您從InputBase
繼承時,您將擁有Value
、 ValueChanged
、 EditContext
等。
protected override bool TryParseValueFromString(string? value, out string result, [NotNullWhen(false)] out string? validationErrorMessage)
{
result = value ?? "";
validationErrorMessage = null;
return true;
}
一般來說,接受的答案是正確的並且工作正常。 唯一需要添加的是代碼示例使用基於默認名稱約定的事件,例如: {PropertyName}Changed
。
[Parameter] public EventCallback<string> BindingValueChanged { get; set; }
但是,您可以覆蓋此命名約定@bind-{Property}:event="{EventCallbackName}"
<MyInputComponent @bind-BindingValue="model.Name" @bind-BindingValue:event="OnValueChanged"/>
.....
[Parameter] public EventCallback<string> OnValueChanged { get; set; }
我花了一些時間才弄清楚dani herreras推薦的選項,所以我想為其他人提供一些清晰的信息。 我想將所有文本輸入更改為Bootstrap 5.0 浮動標簽。 從InputBase<string>
繼承給了我們很多工作。 @CssClass
自動負責應用驗證類,@ @CurrentValue
為我們提供了組件的@bind-Value
。
輸入組件.razor
@using System.Linq.Expressions
@using Microsoft.AspNetCore.Components.Forms
@inherits InputBase<string>
<div class="form-floating mb-3">
<input class="form-control @CssClass" id="@Id" @bind="@CurrentValue">
<label for="@Id">@Label</label>
</div>
<div class="form-control-validation">
<ValidationMessage For="@ValidationFor" />
</div>
@code {
[Parameter, EditorRequired] public Expression<Func<string>> ValidationFor { get; set; } = default!;
[Parameter] public string? Id { get; set; }
[Parameter] public string? Label { get; set; }
protected override bool TryParseValueFromString(string? value, out string result, out string validationErrorMessage)
{
result = value;
validationErrorMessage = null;
return true;
}
}
SomePage.razor
@using System.ComponentModel.DataAnnotations
<EditForm EditContext="@_editContext" OnValidSubmit=@HandleValidSubmit>
<DataAnnotationsValidator/>
<button type="submit" class="btn btn-primary">Submit</button>
<ValidationSummary />
<InputComponent @bind-Value="person.Name" ValidationFor="@(()=>person.Name)" Label="Name" ></InputComponent>
<p>Two way binded value: @person.Name</p>
</EditForm>
@code {
private class ExamplePerson
{
[Required]
public string Name { get; set; }
}
private ExamplePerson person { get; set; } = new ExamplePerson();
private EditContext _editContext;
protected override void OnInitialized()
{
_editContext = new(person);
}
private async void HandleValidSubmit()
{
}
}
此外,我們可以通過進行以下更改來使用 Bootstrap 5.0 class 名稱進行驗證。
protected override void OnInitialized()
{
_editContext = new(person);
_editContext.SetFieldCssClassProvider(new BootstrapValidationClassProvider());
}
public class BootstrapValidationClassProvider : FieldCssClassProvider
{
public override string GetFieldCssClass(EditContext editContext, in FieldIdentifier fieldIdentifier)
{
if (editContext == null)
throw new ArgumentNullException(nameof(editContext));
bool isValid = !editContext.GetValidationMessages(fieldIdentifier).Any();
if (editContext.IsModified(fieldIdentifier))
return isValid ? "is-valid" : "is-invalid";
return isValid ? string.Empty : "is-invalid";
}
}
將 Blazor 與 .NET7 結合使用,您可以執行以下操作:
我的自定義組件.Razor
<input type="text" @bind:get="BindingValue" @bind:set="SetAsync">
@code {
[Parameter]
public string BindingValue { get; set; }
[Parameter]
public EventCallback<string> BindingValueChanged { get; set; }
async Task SetAsync(string value)=> await BindingValueChanged.InvokeAsync(value);
}
}
然后你可以使用:
<MyCustomComponent @bind-BindingValue="whateverVariable" />
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.