Blazor复用Input组件子传父数据为空问题求助
自定义Input组件数据绑定异常排查与解决
问题现象
使用自定义复用Input组件创建新用户资料时,提交新用户时组件内输入的所有数据均为空,但使用标准<input>标签时功能正常,推测是子组件向父组件传递数据出现问题。
相关代码
主页面 AddProfile.razor
<form> <div class="col-md-6"> <Label LabelClass="small mb-1" LabelText="@Loc[nameof(ResourcesEnum.GeneralFirstName)]"/> <Input InputPlaceholder="@Loc[nameof(ResourcesEnum.GeneralEnterFirstName)]" BindValue="@_contact.FirstName" InputClass="form-control" /> </div> ... <div class="btn-wrapper"> <Button BtnClass="btn btn-primary" IconClass="bi bi-plus-lg" OnClick="Submit" /> <Button BtnClass="btn btn-danger" IconClass="bi bi-x-circle" OnClick="() => CancelModalWindow()" DataToggle="modal" DataTarget="#exampleModal"/> </div> </form> @code { private ContactDTO _contact = new ContactDTO(); private List<PartnerDTO>? _partners = new List<PartnerDTO>(); private bool _switchAddPartner = false; private ModalBootstrap? _modalComponent; private string? _returnUrl; private string _submitText = "Save contact"; private string _exam; protected override async Task OnInitializedAsync() { _partners = (await PartnerService.GetAllPartners())?.ToList(); var uri = NavigationManager.ToAbsoluteUri(NavigationManager.Uri); if (QueryHelpers.ParseQuery(uri.Query).TryGetValue("returnUrl", out var url)) { _returnUrl = url!; _submitText = "Save and return"; } } void HandleInputValueChanged(string value) { // Update the input value in the parent component _contact.FirstName = value; } private void HandleInputData(string inputValue) { _contact.FirstName = inputValue; Console.WriteLine($"it is value input: {_contact.FirstName}!!!!!"); } private void NavigateUrlContactsPage() { NavigationManager.NavigateTo("/contacts"); } private void Cancel() { if (!string.IsNullOrEmpty(_returnUrl)) { NavigationManager.NavigateTo(_returnUrl); } else { NavigateUrlContactsPage(); } } private async Task Submit() { Console.WriteLine($"Before Submit: {_contact.FirstName}"); try { var createdContact = await ContactService.CreateContactAsync(_contact); if (!string.IsNullOrEmpty(_returnUrl)) { Console.WriteLine(createdContact.FirstName); var returnUrlWithNewContact = $"{_returnUrl}?newContactId={createdContact.Id}"; NavigationManager.NavigateTo(returnUrlWithNewContact); } else { Console.WriteLine($"Error{_contact.FirstName}"); NavigateUrlContactsPage(); } Snackbar.Add($"➕ {_contact.FullName}", Severity.Success); } catch (Exception ex) { Snackbar.Add($"{@Loc[nameof(ResourcesEnum.GeneralError)]}: {ex.Message}", Severity.Error); } } private void CancelModalWindow() { _modalComponent.ShowModal($"{@Loc[nameof(ResourcesEnum.GeneralConfirmExit)]}", $"{@Loc[nameof(ResourcesEnum.GeneralConfirmExitQuestion)]}",()=>Cancel() ); } }
自定义Input组件 Input.razor
<input class="@InputClass" type="@InputType" placeholder="@InputPlaceholder" @bind="@BindValue"/> @code { [Parameter] public string InputType { get; set; } = "text"; // 默认值避免空类型 [Parameter] public string InputClass { get; set; } [Parameter] public string InputPlaceholder { get; set; } [Parameter] public string BindValue { get; set; } }
问题根源
Blazor中普通[Parameter]是单向绑定:父组件可传递值给子组件,但子组件无法直接修改父组件属性。你的自定义Input组件使用@bind="@BindValue",但BindValue只是普通参数,没有配套回调机制通知父组件更新值,导致输入内容无法同步到父组件的_contact.FirstName中。
解决步骤
1. 修改自定义Input组件,实现双向绑定
添加回调参数BindValueChanged用于通知父组件更新数据,可选添加BindValueExpression支持表单验证:
<input class="@InputClass" type="@InputType" placeholder="@InputPlaceholder" value="@BindValue" @oninput="HandleInputChanged"/> @code { [Parameter] public string InputType { get; set; } = "text"; [Parameter] public string InputClass { get; set; } [Parameter] public string InputPlaceholder { get; set; } // 绑定的值 [Parameter] public string BindValue { get; set; } // 值变化时的回调 [Parameter] public EventCallback<string> BindValueChanged { get; set; } // 用于表单验证的表达式(可选) [Parameter] public Expression<Func<string>> BindValueExpression { get; set; } private async Task HandleInputChanged(ChangeEventArgs e) { var newValue = e.Value?.ToString() ?? string.Empty; // 触发回调通知父组件更新值 await BindValueChanged.InvokeAsync(newValue); } }
或使用Blazor双向绑定语法糖(参数名+Changed的命名约定):
<input class="@InputClass" type="@InputType" placeholder="@InputPlaceholder" @bind-value="@BindValue" @bind-value:event="oninput"/> @code { [Parameter] public string InputType { get; set; } = "text"; [Parameter] public string InputClass { get; set; } [Parameter] public string InputPlaceholder { get; set; } [Parameter] public string BindValue { get; set; } [Parameter] public EventCallback<string> BindValueChanged { get; set; } }
2. 父组件无需额外修改
父组件BindValue="@_contact.FirstName"的写法会自动识别双向绑定,Blazor会自动配对BindValue和BindValueChanged。
验证
修改后,输入框内容会实时同步到父组件的_contact.FirstName,提交时可获取正确输入数据。
内容的提问来源于stack exchange,提问作者Mr Dot
相关产品推荐
相关产品推荐

