Come eseguire l'associazione a due vie sul componente Blazer

Come eseguire l'associazione a due vie sul componente Blazer

Risposta rapida

Citando i documenti di Blazor:

Per la tua pagina:

<EditForm Model="model" OnValidSubmit="Submit">
    <MyInputComponent @bind-BindingValue="model.Name" />
</EditForm>

Il componente figlio 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; }   

}

Avviso

  • Dovresti aumentare le modifiche al binding dal componente children tramite EventCallback<string> BindingValueChanged .
  • Ho scelto BindingValue e BindingValueChanged come identificatori, ma puoi usare solo Value e ValueChanged . Quindi sarà:<MyInputComponent @bind-Value="model.Name" />

Provalo su BlazorFiddle.

Modificato:vedi l'opzione 2 di seguito per una soluzione pulita:

Il tuo controllo all'interno di un EditForm

Se vuoi inserire il tuo componente in un EditForm e gestire le convalide, o intraprendere altre azioni usando l'evento onchange, dovresti aumentare EditContext.NotifyFieldChanged . Hai 2 opzioni per farlo.

Opzione 1:rilancio da EditContext

Puoi ottenere EditContext da CascadeParameter e invoca NotifyFieldChanged a mano:

    [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);

        }
    }

Opzione 2 (consigliata):tramite ereditarietà da InputBase

Puoi ereditare da InputBase<string> e implementa semplicemente TryParseValueFromString . InputBase farà il lavoro per te, quando erediterai da InputBase hai Value , ValueChanged , EditContext , ecc.

protected override bool TryParseValueFromString(string? value, out string result, [NotNullWhen(false)] out string? validationErrorMessage)
{
    result = value ?? "";
    validationErrorMessage = null;
    return true;
}

In generale la risposta accettata è corretta e funziona bene. L'unica cosa da aggiungere è che l'esempio di codice utilizza gli eventi basati sulla convenzione del nome predefinita, ad esempio:{PropertyName}Changed .

[Parameter] public EventCallback<string> BindingValueChanged { get; set; }

Tuttavia puoi ignorare questa convenzione di denominazione @bind-{Property}:event="{EventCallbackName}"

<MyInputComponent @bind-BindingValue="model.Name" @bind-BindingValue:event="OnValueChanged"/>

.....

[Parameter] public EventCallback<string> OnValueChanged { get; set; }