El one-way binding es el flujo de datos en una sola dirección, desde el código C# hacia la interfaz renderizada.
En el artículo anterior capturamos lo que hace el usuario mediante eventos. Ahora vamos a mostrar valores de variables, propiedades y expresiones en el HTML.
A esto lo llamamos One-Way Binding (Enlace Unidireccional). Se llama así porque el flujo de información viaja en un solo sentido: Desde el código C# hacia el HTML.
Si la variable cambia en el código, el HTML se actualiza. Pero si el usuario toca el HTML (por ejemplo, escribiendo en un input), la variable no se entera (aún).
Binding del contenido de texto
La forma más básica de binding es imprimir el valor de una variable dentro de una etiqueta HTML. Como vimos en la sección de sintaxis, esto se hace con la arroba @.
<h3>Perfil de Usuario</h3>
<p>Nombre: @UserName</p>
<p>Nivel: @CalculateLevel()</p>
<p>Último acceso: @LastLogin.ToShortDateString()</p>
@code {
private string UserName = "Luis";
private int Score = 1500;
private DateTime LastLogin = DateTime.Now;
private int CalculateLevel()
{
return Score / 100;
}
}Cada vez que Blazor renderice este componente, evaluará @UserName y sustituirá esa expresión por el valor actual del string.
Recuerda: Blazor renderiza automáticamente cuando ocurre un evento UI (como un clic). Si cambias UserName en un método @onclick, el párrafo <p> se actualizará solo.
Binding de atributos HTML
Además de pintar texto entre etiquetas, podemos usar valores en los atributos HTML.
Esto es fundamental para imágenes, enlaces y clases CSS.
<img src="@AvatarUrl" alt="Foto de @UserName" />
<a href="/usuario/@UserId">Ver Perfil</a>
<div style="background-color: @BgColor; width: @(Progress)%">
@Progress %
</div>
@code {
private string AvatarUrl = "/img/default-user.png";
private string UserName = "Luis";
private int UserId = 42;
private string BgColor = "green";
private int Progress = 75;
}Fíjate que no necesitamos comillas especiales ni sintaxis extraña tipo v-bind o ng-bind. Simplemente usamos C# dentro del atributo.
El caso especial de los atributos booleanos
En HTML, hay atributos que funcionan por su mera presencia, no por su valor. Ejemplos clásicos son disabled, readonly, checked o selected.
- HTML clásico:
<input disabled>(está deshabilitado). - HTML clásico:
<input>(está habilitado).
Si intentáramos hacer esto a la antigua:
<input disabled="@isDisabled">
Podríamos pensar que si isDisabled es false, el atributo disabled="false" haría que el input funcionase. Error. En HTML, disabled="false" sigue deshabilitando el input porque el atributo existe.
Blazor trata de forma especial los atributos booleanos.
Si vinculas un atributo a una variable bool, Blazor eliminará el atributo completamente del DOM si el valor es false, y lo añadirá si es true.
<label>
<input type="checkbox" @onchange="ToggleEdit" /> Editar
</label>
<input type="text" value="Texto de prueba" readonly="@IsReadOnly" />
<button class="btn btn-primary" disabled="@IsSaving">
@(IsSaving ? "Guardando..." : "Guardar")
</button>
@code {
private bool IsReadOnly = true;
private bool IsSaving = false;
private void ToggleEdit()
{
IsReadOnly = !IsReadOnly;
}
}Esta característica nos ahorra escribir mucha lógica condicional fea dentro del HTML.
Clases CSS dinámicas
Gestionar las clases CSS dinámicamente es el día a día del desarrollo frontend (poner un borde rojo si hay error, poner fondo gris si está inactivo).
Aunque podemos concatenar strings, la forma más limpia es usar la expresión condicional ternaria de C# dentro del atributo class.
<div class="alert @(IsError ? "alert-danger" : "alert-success")">
@Message
</div>
<button class="btn @btnColor @(IsActive ? "active" : "")">
Púlsame
</button>
@code {
private bool IsError = false;
private string Message = "Operación correcta";
private bool IsActive = true;
private string btnColor = "btn-primary";
}Para lógicas de clases muy complejas, es recomendable crear una propiedad de solo lectura en el bloque @code que construya el string de clases, manteniendo el HTML limpio.
Limitaciones del one-way binding
Es importante entender que esto es una “proyección”. Si hacemos esto:
<input value="@UserName" />- El input mostrará el valor inicial de
UserName(“Luis”). - Si el usuario borra “Luis” y escribe “Ana”, la variable C#
UserNameSEGUIRÁ VALIENDO “Luis”. - No hay conexión de vuelta.
Si queremos que la variable se actualice cuando el usuario escribe, necesitamos combinar el One-Way Binding (value="@...") con un evento (@onchange="...") que actualice la variable.