如何绑定到使用组件标签助手渲染的组件值

问题描述 投票:0回答:1

我需要在预先存在的视图和页面上使用一些作为剃刀组件构建的自定义输入,但似乎无法使用组件标签帮助器使其工作。例如,我一直在测试的组件代码(来自 https://chrissainty.com/creating-bespoke-input-components-for-blazor-from-scratch/)首先会导致异常,因为 ValueExpression最终为空(据我所知,没有使用标签助手进行绑定的选项)。如果我自己设置 ValueExpression,最终会出现 json 异常(检测到对象循环)。我想也许是因为将参数从标签助手移动到底层组件的机制不支持 Func<> 对象?不确定。

我是否尝试错误地使用标签助手?我在其他地方使用它来渲染独立的组件(如整个 EditForm),这似乎工作正常,但如何让它在这个特定的用例中工作让我困惑:(

在 .cshtml 文件内我希望控件呈现在:

<component type="typeof(MyComponent)" render-mode="ServerPrerendered" param-ValueExpression="(Func<string>)(() => LocalProperty)" />

我的组件.razor

<input class="_fieldCssClasses" value="@Value" @oninput="HandleInput" />

@if (_showValidation) {
    <div class="validation-message">You must provide a name</div>
}

@code {
    private FieldIdentifier _fieldIdentifier;
    private string _fieldCssClasses => EditContext?.FieldCssClass(_fieldIdentifier) ?? "";
    private bool _showValidation = false;

    [CascadingParameter] private EditContext EditContext { get; set; }

    [Parameter] public string Value { get; set; }
    [Parameter] public EventCallback<string> ValueChanged { get; set; }
    [Parameter] public Expression<Func<string>> ValueExpression { get; set; }
    [Parameter] public bool Required { get; set; }

    protected override void OnInitialized() {
        _fieldIdentifier = FieldIdentifier.Create(ValueExpression);
    }

    private async Task HandleInput(ChangeEventArgs args) {
        await ValueChanged.InvokeAsync(args.Value.ToString());

        if (EditContext != null) {
            EditContext.NotifyFieldChanged(_fieldIdentifier);
        } else if (Required) {
            _showValidation = string.IsNullOrWhiteSpace(args.Value.ToString());
        }
    }
}
c# data-binding blazor blazor-server-side asp.net-core-tag-helpers
1个回答
0
投票

因此,为了解决这个问题,我只是在内部组件周围创建了一个特定于用例的包装组件,确保还传入一个 Id,内部组件将分配给它正在渲染的输入的 name 和 id 属性(允许它提交表单时“绑定”),然后将包装器组件包含在页面/视图上。包装器只是满足内部组件的依赖关系,如果依赖关系更复杂(如 Func<> 对象),组件标签帮助器不会提供机制。

MyComponentWrapper.razor:

<div class='purdy'>
    <MyComponent Id="@Id" @bind-Value="Value"></MyComponent>
</div>
...
@code {
    [Parameter]
    public string Id { get; set; }
    [Parameter]
    public string Value { get; set; }
    ...
}

MyContainingPage.cshtml:

<component type="typeof(MyComponentWrapper)" 
  render-mode="ServerPrerendered" 
  param-Id="myFormInput" 
  param-Value="LocalProperty" />
  ...
© www.soinside.com 2019 - 2024. All rights reserved.