In this article, I will demonstrate how to communicate between different Blazor components using a well-known library named “MediatR.” Notification Handler is one of the features that are included with the MediatR.
When a user types in the textbox, the textbox input change event publishes the command, and the component MainLayout and the Counter component are listening for the event and updating the background colour of their respective components. Here, I am going to build an application that does this. (Note: This technique passes the event in one way only)
Let’s understand how the code works. In the Index.razor
file, I have one input textbox that publishes the event details in our case colour name using the MediatR
publish command, and then the MainLayout
and Counter
command listening to the event by using the INotificationHandler
Index.razor
@page "/"
<Counter></Counter>
<input type="text" @oninput="(async args=>await mediator.Publish(new ColorChangeNotification(){Color = args.Value.ToString()}))" />
@code {
}
ColorChangeNotification.cs
using Blazor.Mediator.Pages;
using MediatR;
namespace Blazor.Mediator.Pages
{
public class ColorChangeNotification : INotification
{
public string Color { get; set; }
}
public class ColorChangedArgs : EventArgs
{
public string Color { get; set; }
}
public partial class Counter : INotificationHandler<ColorChangeNotification>
{
public static event EventHandler<ColorChangedArgs> OnColorChanged;
public Task Handle(ColorChangeNotification notification, CancellationToken cancellationToken)
{
OnColorChanged?.Invoke(this, new ColorChangedArgs() { Color = notification.Color });
return Task.CompletedTask;
}
}
}
namespace Blazor.Mediator.Shared
{
public partial class MainLayout : INotificationHandler<ColorChangeNotification>
{
public static event EventHandler<ColorChangedArgs> OnColorChanged;
public Task Handle(ColorChangeNotification notification, CancellationToken cancellationToken)
{
OnColorChanged?.Invoke(this, new ColorChangedArgs() { Color = notification.Color });
return Task.CompletedTask;
}
}
}
Let’s walk through the above code as you know that when the razor page transpiles to C# code, it creates a partial class named with razor file. In our example, listeners are MainLayout and Counter components, so I have made two classes and then implemented the interface, which is included in the MediatR library. INotificationHandler triggers when the MediatR publishes command is triggered in our case; the input textbox is sending the colour value.
Make sure that the namespace of the partial class is the same; otherwise code will not work.
How to subscribe to the publish event in the component.
As we added events in our component classes, all the MediatR-related logic is now available in our component. Now subscribe to the OnColorChanged
event in the component OnInitialized
method, and you are done :)
private string color = "";
protected override void OnInitialized()
{
OnColorChanged += (sender, changed) =>
{
color = changed.Color;
InvokeAsync(StateHasChanged);
};
}
MainLayout.razor
@inherits LayoutComponentBase
<PageTitle>Blazor.Mediator</PageTitle>
<div class="page">
<div class="sidebar">
<NavMenu />
</div>
<main>
<div class="top-row px-4">
<a href="https://docs.microsoft.com/aspnet/" style="background-color: @color" target="_blank">About</a>
</div>
<article class="content px-4">
@Body
</article>
</main>
</div>
@code
{
private string color = "";
protected override void OnInitialized()
{
OnColorChanged += (sender, changed) =>
{
color = changed.Color;
InvokeAsync(StateHasChanged);
};
}
}
Counter.razor
@page "/counter"
@using Blazor.Mediator
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status" style="background-color: @color">Current count: @currentCount</p>
<h1></h1>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private string color;
protected override void OnInitialized()
{
OnColorChanged += (sender, changed) =>
{
color = changed.Color;
InvokeAsync(StateHasChanged);
};
}
private void IncrementCount()
{
currentCount++;
}
}