You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 08:24:54