Blazor and Supabase, Real Time - Part 3

Continuation of the article on Blazor and Supabase, in this part we will discover and set up real time
Banner Image Blazor and Supabase, Real Time - Part 3
Posted by phnogues on November 05, 2024

Version française ici

Part 1 : Database
Part 2 : Authentication
Part 3 : Real Time


Supabase also manages real-time functionality. In this article, we’ll explore two ways to use real-time features:

I invite you to clone the GitHub repository for the full code: https://github.com/phnogues/Blazor.Supabase/

Prerequisites:

Case 1 - Trigger from the database

1- Enable real-time for the table:
In the relevant table on Supabase’s interface, activate real-time with the "Realtime Off/On" button (Table Editor / The table / button in the top right corner).

2- Code c# :

[Inject]
Supabase.Client _supabase { get; set; }
	
private RealtimeChannel? _crepesChannel;
	
protected override async Task OnInitializedAsync()
{
	await _supabase.Realtime.ConnectAsync();

	// channel for crepes changes
	_crepesChannel = _supabase.Realtime.Channel("public:crepes");
	if (!_crepesChannel.IsJoined)
	{
		_crepesChannel.Register(new PostgresChangesOptions("public", "crepes"));
	}
	_crepesChannel.AddPostgresChangeHandler(PostgresChangesOptions.ListenType.Inserts, CrepeInsertedHandler);
	_crepesChannel.AddPostgresChangeHandler(PostgresChangesOptions.ListenType.Updates, CrepeUpdatedHandler);

	await _crepesChannel.Subscribe();
}
private void CrepeInsertedHandler(IRealtimeChannel _, PostgresChangesResponse change)
{
	var crepe = change.Model<Crepe>();
	_notificationService.Notify(NotificationSeverity.Success, "New crepe inserted", $"{crepe.Name}");
	Events.Add($"New crepe inserted: {crepe.Name}");

	this.InvokeAsync(() => this.StateHasChanged());
}

private void CrepeUpdatedHandler(IRealtimeChannel _, PostgresChangesResponse change)
{
	var crepe = change.Model<Crepe>();
	_notificationService.Notify(NotificationSeverity.Success, "Crepe updated", $"{crepe.Name}");
	Events.Add($"Crepe updated: {crepe.Name}");

	this.InvokeAsync(() => this.StateHasChanged());
}

Case 2 : Using message broadcasting

private RealtimeChannel? _kitchenChannel;

protected override async Task OnInitializedAsync()
{
	// Realtime
	await _supabase.Realtime.ConnectAsync();
	_kitchenChannel = _supabase.Realtime.Channel("order");
	if (!_kitchenChannel.IsJoined)
	{
		_kitchenChannel.Register<Order>(true, true);
	}

	await _kitchenChannel.Subscribe();
}

// Méthode à appeler depuis un bouton ou autre
private async Task Order(CrepeDto crepe)
{
	_kitchenChannel?.Broadcast<Order>()?.Send("order", new Order { Name = crepe.Name, Price = crepe.Price, Date = DateTime.UtcNow }); ;
}

[Inject]
Supabase.Client _supabase { get; set; }

private RealtimeChannel? _orderChannel;

protected override async Task OnInitializedAsync()
{
	await _supabase.Realtime.ConnectAsync();

	// channel for orders
	_orderChannel = _supabase.Realtime.Channel("order");
	if (!_orderChannel.IsJoined)
	{
		_orderChannel.Register<Order>(true, true);
		_orderChannel?.Broadcast<Order>()?.AddBroadcastEventHandler(HandleOrderBroadcastReceived);
	}

	await _orderChannel.Subscribe();
}

public class Order : BaseBroadcast
{
	[JsonProperty("name")]
	public string Name { get; set; }

	[JsonProperty("price")]
	public float Price { get; set; }

	[JsonProperty("date")]
	public DateTime Date { get; set; }
}
private void HandleOrderBroadcastReceived(IRealtimeBroadcast sender, BaseBroadcast? args)
{
	var order = _orderChannel?.Broadcast<Order>()?.Current();

	if (order == null) return;

	_notificationService.Notify(NotificationSeverity.Warning, "New order ! ", $"{order.Name}");
	Events.Add($"New order: {order.Name} {order.Price}€ {order.Date}");

	this.InvokeAsync(() => this.StateHasChanged());
}
.Net
.Net Blazor Supabase

Comments :