En este post vamos a ver como enviar o compartir información entre distintos componentes en blazor, para ello veremos las 3 formas de las que disponemos.
Índice
1 - Valores en cascada en blazor
Como vimos en el post de la creación de componentes, podemos enviar valores de un componente padre a uno hijo, para ello disponemos de dos opciones, utilizar la etiqueta <cascadingValue>
o enviarlo como parámetro.
<!-- Elemento padre -->
<div class="main">
<div class="content px-4">
<CascadingValue Value="Bordercolor">
@Body
</CascadingValue>
</div>
</div>
@code{
private readonly string Bordercolor="red";
}
En el ejemplo anterior estamos enviando desde el elemento padre el parámetro BorderColor, el cual lo recibimos en el elemento hijo y lo aplicamos a la regla css.
<!-- Elemento hijo -->
<div class="row">
...
<div class="col-sm-3" style="border: 1px solid @BorderColor">
<b>Email:</b> @PersonalProfile.Email
</div>
...
</div>
@code {
[Parameter]
public PersonalProfileDto PersonalProfile { get; set; }
[CascadingParameter]
public string BorderColor { get; set; }
}
- Para ver más en detalle el funcionamiento, por favor revisa este post.
2 - EventCallbacks en blazor
Antes de continuar, decir que tanto EventCallback
como EventCallback<T>
fueron funcionalidades añadidas en blazor a partir de la versión de net core 3 preview 3
.
Anteriormente para hacer una callback utilizabamos un delegado Action
o Func
, y la teoría sigue siendo la misma, la única diferencia es que anteriormente debíamos llamar al método StateHasChanged
para indicarle al componente que hiciera el renderizado otra vez.
Lo que ha cambiado con la llegada de EventCallback
es que hace esa llamada a StateHashChanged
de forma automática.
Este tipo de eventos son muy útiles principalmente cuando un componente hijo debe generar un cambio en el componente padre.
Como podemos observar, en el elemento padre, mandamos al hijo un método como parámetro:
<!-- Parent Component -->
<div>@Mensaje</div>
<PerfilPersonal Profile="@Name" OnClick="ClickCallback"></PerfilPersonal>
<Contacto />
@code{
public string Mensaje = "Este es el mensaje en el elemento padre";
void ClickCallback(string mensajeNuevo)
{
Mensaje = mensajeNuevo;
}
}
El cual recibimos en el hijo como parámetro, indicando el tipo EventCallback<string>
utilizamos string
porque es el tipo de parámetro que recibe nuestro método.
[Parameter]
public EventCallback<string> OnClick { get; set; }
Y para ejecutarlo, en el componente hijo debemos incluirlo como evento en alguno de nuestros items, en mi caso como onclick de un botón.
<button @onclick="@(() => OnClick.InvokeAsync($"Perfil del usuario {PersonalProfile.FirstName} {PersonalProfile.LastName} (enviado desde el hijo)."))">Lanzar evento padre</button>
Resultado:
3 - State container en blazor
Finalmente vamos a ver el state containe
r, el cual nos permite administrar múltiples componentes de nuestra aplicación simultáneamente, sin que estos estén relacionados entre sí directamente.
Para ello debemos hacer una clase e inyectarla en los componentes donde queramos trabajar con ella. Cuando la definimos en nuestro contenedor de dependencias, debemos definirla como singleton
si la aplicación es web assembly, o scoped
si la aplicación es server side.
Para este ejemplo crearemos la lógica de cambiar el color de los títulos en nuestra aplicación, pero una versión profesional podría ser el modo nocturno, la lógica es la misma, extendido a la aplicación completa.
public class StateContainer
{
public string SelectedCssClass { get; private set; }
public event Action CambiarColor;
public void AsignarColorCss(string newCssClass)
{
SelectedCssClass = newCssClass;
ExecuteAction();
}
private void ExecuteAction() => CambiarColor?.Invoke();
}
Como podemos observar, nuestra clase StateContainer
es una clase normal. Tiene una propiedad que almacena el valor de la clase css, un método público donde podemos cambiar ese valor y finalmente un evento CambiarColor
que nos permite subscribirnos desde otros componentes.
En cada componente donde queremos tener acceso al valor que va a cambiar debemos suscribirnos al evento CambiarColor
que exponse nuestra clase StateContainer
.
@page "/perfil/{Name}"
@using WebPersonal.FrontEnd.WebApp.Componentes
@inject StateContainer stateContainer
@implements IDisposable
<div class="@stateContainer.SelectedCssClass">@Mensaje</div>
@code{
protected override void OnInitialized()
{
stateContainer.CambiarColor += StateHasChanged;
}
public void Dispose()
{
stateContainer.CambiarColor -= StateHasChanged;
}
}
Haciendo esto, nos aseguramos que cuando la clase cambie, el método StateHasChanged
será invocado y así volverá a renderizar el componente con la nueva clase aplicada.
No olvides implementar IDisposable
, para que cuando no estés utilizando el componente este se desuscriba del evento CambiarColor
. De lo contrario podría causar un memory leak.
Finalmente solo nos queda crear los dos botones para cambiar del modo nocturno al normal.
Para ello lo único que debemos hacer es llamar con el evento onclick al método AsignarColorCss
pasando como parámetro el valor deseado.
<!-- Boton modo "normal" -->
@inject StateContainer stateContainer
<button @onclick="SetCssNormal">Normal</button>
@code {
void SetCssNormal()
{
stateContainer.AsignarColorCss("negro");
}
}
<!-- Boton modo "nocturno" (rojo) -->
@inject StateContainer stateContainer
<button @onclick="SetCssNormal">Rojo</button>
@code {
void SetCssNormal()
{
stateContainer.AsignarColorCss("rojo");
}
}
Y este es el resultado, cuando pulsamos en el enlace, podemos ver como cambia el color
Conclusión
- Hoy hemos visto tres formas diferentes de mantener comunicación entre diferentes componentes en blazor.
- Hemos visto enviando información desde padres a hijos, utilizando los valores en cascada.
- Hemos visto enviar información desde un hijo a un padre utilizando EventCallback.
- Finalmente, hemos visto cómo compartir información entre cualquier número de componentes sin que estos estén directamente relacionados entre sí utilizando State Container.