An unofficial set of extensions for developing Nui interfaces with Blazor WASM in .NET 8
- Attribute-based Nui Message handling
[NuiMessageHandler("showui:true")]
- Service-based Nui Callback triggering
@inject INuiCallbackService
await NuiCallbackService.TriggerNuiCallbackAsync("getItemInfo", new { item = "phone" });
System.Text.Json
for JSON Serialization & Deserialization
-
For Nui Message handling, the NuiMessageListener must be injected as a root-component in index.html, and your component(s) must inherit NuiComponent
- Add
<template id="nui-message-listener"></template>
to yourindex.html
in the<body>
- Add
builder.RootComponents.Add<NuiMessageListener>("#nui-message-listener");
in yourProgram.cs
- Add
@inherits NuiComponent
in your component/razor page - Add
[NuiMessageHandler("<identifier>")]
to any static or instanced method in your component
- Add
-
For triggering Nui Callbacks, NuiCallbackService must be added to your service collection
- Add
builder.Services.AddNuiServices();
in yourProgram.cs
- Inject in your page with
@inject INuiCallbackService NuiCallbackService
- Add
NuiMessageListener
&NuiMessageHandler
requires/uses a specific string field in the sending-message to determine which method to invoke- The field can be configured in
builder.Services.AddNuiServices();
- When
NuiMessageListener
receives an Nui message, it checks for[NuiMessageHandler]
attributed methods with a matching identifier name in the received message
- The field can be configured in
- Currently, you may only have one
NuiMessageListener
per identifier-string - Configure the internal
JsonSerializerOptions
and the identifier-string inbuilder.Services.AddNuiServices();
builder.Services.AddNuiServices(options =>
{
options.JsonSerializerOptions.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
options.MessageHandlerIdentifierField = "id";
});
client.lua
RegisterCommand('ui', function()
SendNUIMessage({ type = "blazor:show-ui"})
end)
RegisterCommand('ui-increment', function()
SendNUIMessage({ type = "blazor:increment" })
end)
-- Assumes args[1] is an integer
RegisterCommand('ui-set', function(source, args, user)
SendNUIMessage({
type = "blazor:set",
count = tonumber(args[1])
})
end)
App.razor
@using CitizenFX.Extensions.Blazor.WebAssembly
@inherits NuiComponent
<div style="text-align: center; color: aquamarine">
@if (_showUi)
{
<h1>I'm a Nui in Blazor!</h1>
@if (_count >= 3)
{
<h2>Count: @_count</h2>
}
}
</div>
@code {
private bool _showUi = false;
private int _count = 0;
[NuiMessageHandler("blazor:increment")]
public async Task OnIncrement()
{
Interlocked.Increment(ref _count);
StateHasChanged(); // Tell Blazor to re-render the page
}
[NuiMessageHandler("blazor:set")]
public async Task SetCount(int count)
{
Interlocked.Exchange(ref _count, count);
StateHasChanged(); // Tell Blazor to re-render the page
}
[NuiMessageHandler("blazor:show-ui")]
public void OnShowUi()
{
_showUi = true;
StateHasChanged(); // Tell Blazor to re-render the page
}
}
client.lua
RegisterCommand('add-item', function()
SendNUIMessage({
type = "blazor:add-item",
itemId = 69,
})
end)
RegisterNUICallback('addItemCallback', function(data, cb)
SendNUIMessage({
type = "blazor:callback"
})
end)
App.razor
@using CitizenFX.Extensions.Blazor.WebAssembly
@using CitizenFX.Extensions.Blazor.WebAssembly.Services
@inherits NuiComponent
@inject INuiCallbackService NuiCallbackService
<div style="text-align: center; color: aquamarine">
<h1>I'm a Nui in Blazor!</h1>
<h3>Last item added: @_lastItemAdded</h3>
@if (_recievedFromCallback)
{
<h3>Hello from our Nui callback!</h3>
}
</div>
@code {
private bool _recievedFromCallback = false;
private string _lastItemAdded = "None";
[NuiMessageHandler("blazor:add-item")]
public async Task AddItem(int itemId)
{
_lastItemAdded = itemId.ToString();
StateHasChanged(); // Tell Blazor to re-render the page
await NuiCallbackService.TriggerNuiCallbackAsync("addItemCallback", new { itemId = itemId });
}
[NuiMessageHandler("blazor:callback")]
public void FromCallback()
{
_recievedFromCallback = true;
StateHasChanged(); // Tell Blazor to re-render the page
}
}