InvokerCommands
A button says which element it acts on and what it does to it, and the browser wires the two together - no click handler, no id plumbing, and none of the focus management to get wrong.
@inject Bit.Butil.InvokerCommands invokerCommandsMDN reference
show-modal, close, request-close,
toggle-popover, show-picker and the media commands are carried out by
the browser itself - correctly, including the top layer and focus restoration. A command starting
with -- is yours: the browser dispatches the event and does nothing else.
IsSupported is false the button does nothing at all, so keep an ordinary click
handler as the fallback.
True when the runtime implements command/commandfor and CommandEvent. During prerender/SSR the check returns false rather than throwing.
@inject Bit.Butil.InvokerCommands invokerCommands
var supported = await invokerCommands.IsSupported();Points the button at the dialog with the built-in show-modal command. After wiring, clicking the button opens the dialog with no C# involved at all - the browser does it, including the top layer and focus restoration. Butil sets the commandForElement property rather than the commandfor attribute, because the attribute takes an id and a Blazor-rendered element often has none.
<button @ref="_invoker">Open</button>
<dialog @ref="_dialog">…</dialog>
await invokerCommands.SetCommandFor(_invoker, _dialog, "show-modal");A command starting with -- is dispatched at the target and otherwise ignored by the browser, which is what makes it a declarative way to wire your own behaviour. The event fires on the target, not the button, so one handler serves however many invokers point at it.
_sub = await invokerCommands.OnCommand(_panel, args =>
{
if (args.Command == "--refresh") Reload();
InvokeAsync(StateHasChanged);
});
await invokerCommands.SetCommandFor(_refreshButton, _panel, "--refresh");0API reference
ValueTask<bool> IsSupported()ValueTask<bool> SetCommandFor(ElementReference invoker, ElementReference target, string command)ValueTask<bool> ClearCommandFor(ElementReference invoker)ValueTask<string> GetCommand(ElementReference invoker)Task<ButilSubscription> OnCommand(ElementReference target, Action<CommandEventArgs> handler)ValueTask DisposeAsync()