通过多个组件进行双向绑定

Posted

技术标签:

【中文标题】通过多个组件进行双向绑定【英文标题】:Two-way binding through multiple components 【发布时间】:2020-02-24 21:31:36 【问题描述】:

我正在尝试将模型字段绑定到控件,我让它在表单上工作,但我正在尝试重构组件,以便我可以在整个程序中重用控件及其属性。

这里有一些 sn-ps 试图描述我的情况:

示例模型

public class MyModel

  public DateTime DateOpened  get; set; 

在 MyModelFormBase.cs 中使用

public class MyModelFormBase : ComponentBase

  protected MyModal data = new MyModel();

用于 MyModelForm.razor

<MyForm Model="@data" AddFunction="@InsertMyModel" DataDismiss="MyModelForm">
  <MyDateInput InputId="dateOpened" InputName="Date Opened" @bind-InputValue="@data.DateOpened" />
</MyForm>

MyForm.razor,使用 blazorstrap

<BSForm Model="@Model" OnValidSubmit="@AddFunction"
  @ChildContent
  <BSButton Color="Color.Primary" 
            ButtonType="ButtonType.Submit" 
            data-dismiss="@DataDismiss">
  Submit</BSButton>
</BSForm>

@code 
  [Parameter]
  public Object Model  get; set;
  [Parameter]
  public RenderFragment ChildContent  get; set; 
  [Parameter]
  public EventCallback AddFunction  get; set; 
  [Parameter]
  public string DataDismiss  get; set; 

MyDateInput.razor,使用 blazorstrap


<BSFormGroup>
  <BSLabel For="@InputId">@InputName</BSLabel>
  <BSInput InputType="InputType.Date" Id="@InputId" 
            @bind-Value="@InputValue"
            ValidateOnChange="true"
            @onchange="UpdateData"
   />
  <BSFormFeedback For="@(() => InputValue)"/>
</BSFormGroup>

@code 
    [Parameter]
    public DateTime InputValue  get; set; 
    [Parameter]
    public EventCallback<DateTime> InputValueChanged  get; set; 

    [Parameter]
    public string InputId  get; set; 

    [Parameter]
    public string InputName  get; set; 

    private async Task UpdateData()
    
        await InputValueChanged.InvokeAsync(InputValue);
    

我的服务提供的默认数据正确显示在控件中,因此它正确地向下绑定,但不会将任何更改传播回模型。 :(

目标是能够保留一个MyDateInput 组件,该组件在整个应用程序中重复,该组件以两种方式与模型绑定,而不管它通过的组件层。 有任何想法吗?

【问题讨论】:

Read the doc 【参考方案1】:

在有这么多代码缺失或未知的情况下回答您的问题真的很令人生畏。不过,我会尽力提供一些帮助,希望能帮助您解决问题。

    这段代码:

    等待 InputValueChanged.InvokeAsync(InputValue);

我猜是一个回调来更新绑定属性 MyModel.DateOpened 的值,对吧?如果不是,它应该这样做。在任何情况下,该属性都应该使用 PropertyAttribute 属性进行注释...

可能是双向数据绑定不起作用的原因。

请注意,您的 MyDateInput 组件可能还需要接收 ValueExpression 值。我不能肯定地说,因为并非所有代码都可用,所以请作为警告:

[Parameter] public Expression<Func<string>> ValueExpression  get; set; 

我会在答案的最后放一个小样本来说明这一点。

    你确定这有效吗?编译器应该在狂吠:

    @bind-Value="@InputValue" ValidateOnChange="true" @onchange="UpdateData"

    告诉你你正在使用两个 onchange 事件。通常应该是这样的

    value="@InputValue" ValidateOnChange="true" @onchange="UpdateData",但我无法确定,因为我看不到 BSInput 是如何实现的...

      注意:BSForm 在@ChildContent 之前缺少一个结束标记

示例代码:

RazorInputTextTest.razo
-----------------------


@page  "/RazorInputTextTest"

<span>Name of the category: @category.Name</span>

<EditForm Model="@category">
   <RazorInputText Value="@category.Name" ValueChanged="@OnValueChanged" ValueExpression="@(() => category.Name)" />

</EditForm>


@code
    private Category category  get; set;  = new Category  ID = "1", Name = "Beverages" ;


    private void OnValueChanged(string name)
    

        category.Name = name;
    




 RazorInputText.razor
 --------------------



<div class="form-group">
    <InputText class="form-control" @bind-Value="@Value"></InputText>
</div>

@code

    private string _value  get; set; 

    [Parameter]
    public string Value
    
        get  return _value; 
        set
        
            if (_value != value) 
                _value = value;
                if (ValueChanged.HasDelegate)
                
                    ValueChanged.InvokeAsync(value);
                
            


        
    


    [Parameter] public EventCallback<string> ValueChanged  get; set; 
    [Parameter] public Expression<Func<string>> ValueExpression  get; set; 

希望这会有所帮助...

【讨论】:

以上是关于通过多个组件进行双向绑定的主要内容,如果未能解决你的问题,请参考以下文章

vue组件双向绑定key的作用

Vue 3 通过双向绑定将反应对象传递给组件

和组件进行双向绑定(笔记)

antd表单组件的双向绑定

微信小程序中的数据双向绑定

Angular自定义组件实现数据双向数据绑定