Saltar al contenido

¿Cuándo usar ValueChanged y ValueExpression en Blazor?

Solución:

De hecho, has olvidado el tercer elemento de este patrón: Value. Esta “trinidad” de propiedades se utiliza con frecuencia para el enlace de datos bidireccional de componentes. En particular, estas propiedades se emplean dentro de los componentes integrados del formulario Blazor, como <InputText>.

Veamos un ejemplo:

<InputText @bind-Value="employee.FirstName" />
  1. Value es una propiedad proporcionada en forma de @bind-Value="model.PropertyName".

  2. ValueChanged es de tipo EventCallback<TValue>. Significa una devolución de llamada que actualiza el valor vinculado. Como puede ver, no lo usamos en el ejemplo anterior; no es necesario. El compilador conoce su trabajo y se encarga de esto, lo que significa que agrega un EventCallback “delegar” con todos los ajustes necesarios a sus espaldas.

  3. ValueExpression, finalmente, se refiere a una expresión que identifica el valor enlazado. El compilador lo crea automáticamente y rara vez, si es que alguna vez, tiene que configurarlo.

Ahora comparemos lo anterior con el siguiente código. El siguiente ejemplo crea un enlace de datos bidireccional entre un componente principal y un componente secundario. Sin embargo, en lugar de utilizar el estándar “trinity” (Value, ValueChanged, ValueExpression), replicaremos el patrón subyacente por nosotros mismos:

ParentComponent.razor:

<ChildComponent @bind-Text="FirstName" />

@code {
    [Parameter]
    public string FirstName { get; set; }
}

ChildComponent.razor:

<input @bind="Text" />

@code {
    private string text;

    [Parameter]
    public string Text
    {
        get { return text; }
        set
        {
            if (text != value) {
                text = value;
                if (TextChanged.HasDelegate)
                {
                    TextChanged.InvokeAsync(value);
                }
            }
        }
    }

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

El incorporado <InputText> y nuestra costumbre <ChildComponent> son básicamente lo mismo!


Para responder a su otra pregunta …

Cuando voy a usar ValueChanged y ValueExpression en Blazor ?? Estoy creando un contenedor de una entrada de otra biblioteca, ¿es este un caso para usar esta trinidad?

Como se explicó anteriormente, ValueChanged y ValueExpression son propiedades definidas en los componentes integrados de Blazor, y la mayoría de las veces no necesitará usarlas directamente.

Mire nuevamente los dos componentes que he definido anteriormente: <ParentComponent> y <ChildComponent>. Cambio Text y TextChanged para Value y ValueChanged, y mis componentes siguen siendo válidos y funcionan correctamente. La única diferencia está en el nombre. Que hago en el <ChildComponent>? Defino una propiedad de parámetro llamada Text (representa Value). Como quiero habilitar el enlace de datos bidireccional entre los componentes principal y secundario, también necesito definir una propiedad de parámetro llamada aquí TextChanged (representa ValueChanged). Text va a TextChanged, Value va a ValueChanged, y Year va a YearChanged. La nomenclatura es solo una convención. El punto principal es que tienes que definir una propiedad y un EventCallback del mismo tipo de datos que la propiedad.

Dentro del componente principal proporciono la propiedad de la siguiente manera:

<ChildComponent @bind-Text="NameOfAPropertyDefinedInTheParentComponent" /> o <ChildComponent @bind-Value="NameOfAPropertyDefinedInTheParentComponent" /> o <ChildComponent @bind-Year="NameOfAPropertyDefinedInTheParentComponent" />

En mis componentes anteriores, también hay código, como por ejemplo en el componente hijo, que invoca el TextChanged delegar para devolver un valor al componente principal; esto es exactamente lo que ValueChanged lo hace el delegado en los componentes en los que está definido. Pero usted, como usuario, no tiene que usarlo. Mira mis componentes … Funcionan perfectamente bien. No es necesario tocar. Si usted, como usuario de mi componente, desea subclasificarlo, entonces necesita saber lo que está haciendo y cómo subclasificar un componente Blazor correctamente. Pero mis componentes, presentados parcialmente aquí, son relativamente simples.

Suponga que desea crear una entrada de contraseña basada en <InputText>, que no solo es factible sino también bastante fácil. En ese caso, no va a cambiar nada más que el aspecto del <InputText> componente para que los símbolos de asterisco se muestren en lugar del texto normal. El resto del componente no se modifica. No es necesario que maneje los eventos y demás. Esto, por supuesto, no significa que el autor de un componente nunca necesitará llamar al EventCallback desde algún lugar de su código. Dicho esto, nunca he tenido una buena razón para activar la ValueChanged delegado al usar el <InputText> componente. Y solo una vez tuve que proporcionar un ValueExpression, ya que el compilador no pudo identificar el valor consolidado. (Lo buscaré, y si lo encuentro lo publicaré aquí …)

Me gustaría agregar algunos casos de uso para ValueChanged y ValueExpression,

En primer lugar, como dijo enet, estas propiedades son más como una trinidad de propiedades donde tienes Foo, FooChanged y FooExpression y se usa en el enlace de datos bidireccional, por ejemplo @bind-Foo="SomeProperty".

Para crear un componente personalizado con una propiedad que se pueda utilizar con @bind- debe proporcionar estas 3 propiedades (solo proporcionando Foo y FooChanged también funciona) como [Parameter] y llama FooChanged cuando cambia la propiedad dentro de su componente personalizado.

por ejemplo, de enet

[Parameter]
public TValue Foo
{
    get => text
    set
    {
        if (text != value) {
            text = value;
            if (FooChanged.HasDelegate)
            {
                FooChanged.InvokeAsync(value);
            }
        }
    }
}

[Parameter]
public EventCallback<TValue> FooChanged { get; set; }

[Parameter]
public Expression<Func<TValue>> FooExpression { get; set; }  

Añadiendo el @bind-Foo sería lo mismo que pasar Value y ValueChanged, la única diferencia es que @bind- solo establecerá la propiedad, pero si agrega la suya ValueChanged, puede hacer lo que quiera (Validar, Cambiar el valor para configurar, etc.).

Casos de uso

1 – Creando un componente que envuelve otro componente con @bind-

Si tiene un componente que ya tiene un @bind-Foo y desea crear un componente además de eso y aún pasar como parámetro @bind-Foo, puede tener solo una propiedad y pasar a @bind-Foo, debe pasar propiedades a Foo, FooChanged y / o FooExpression.

p.ej

CustomInputWrapper.razor

<div>
    <p>My custom input wrapper</p>
    @* If you pass @bind-Value it won't work*@
    @* You need to pass the properties that are used in the bind*@
    <InputText Text="@Value" TextChanged="@ValueChanged" TextExpression="@ValueExpression" />
</div>

@code {    
    [Parameter]
    public virtual string Value { get; set; }

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

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

Esta situación de empaquetar otro componente sucederá mucho si está haciendo muchos componentes personalizados o no desea usar directamente algún componente de terceros.

Ejemplo de mi proyecto: en mi proyecto estoy usando MatBlazor y Telerik, pero no todos los componentes en ambas bibliotecas son completamente estables, así que creé un contenedor alrededor de todos los componentes y un día, cuando una de estas bibliotecas está completamente estable, cambiaré para usar solo una biblioteca. Hacer esto me permite tener mis componentes personalizados y si quiero cambiar uno, solo cambio una cosa en mi componente personalizado y cambio toda la aplicación.

2 – Agregar valor predeterminado

Si desea tener un valor predeterminado dentro de un componente personalizado, “puede” simplemente pasar un valor predeterminado a la propiedad.

[Parameter]
public virtual DateTime Value { get; set; } = new DateTime(/* some default value*/);

Pero esto tiene un gran problema si usa este componente dentro de un formulario.

Por qué? Porque solo cambiará el valor dentro de su componente, pero si se pasa una propiedad en @bind-Value no se cambiará.

Para agregar este valor predeterminado y hacer que funcione en el enlace de datos bidireccional, debe llamar ValueChanged y pasar el valor predeterminado. Esto hará que su componente tenga el valor predeterminado y también cambiará cualquier propiedad en @bind-Value para tener el valor predeterminado.

p.ej

// Lifecycle after all parameters are set
protected override void OnParametersSet()
{
    // Check if the ValueChanged is set
    if (ValueChanged.HasDelegate)
    {
        ValueChanged.InvokeAsync(DateTime.Now);
    }
}

3 – Caso de uso donde realmente lo necesita FooExpression

Cuando tienes un tipo que acepta valores NULL, p. Ej. int?, a veces, cuando el valor es null, no puede saber su tipo, por lo que debe aprobar FooExpression para que pueda obtener el tipo por reflexión. Aquí hay un ejemplo en el que debe usarlo.


El caso de uso de estas propiedades se utilizará más si está creando componentes personalizados y tiene que trabajar con propiedades vinculadas o cambiar cómo funcionará la vinculación.

Si solo está utilizando componentes ya fabricados, será raro que tenga que usarlos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *