loading
Note:
Built-in commands are handled for youshow-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.
Warning:
Chromium and Safari Where IsSupported is false the button does nothing at all, so keep an ordinary click handler as the fallback.

Support check

IsSupported

True when the runtime implements command/commandfor and CommandEvent. During prerender/SSR the check returns false rather than throwing.

C#
@inject Bit.Butil.InvokerCommands invokerCommands

var supported = await invokerCommands.IsSupported();
Live sample
support check output
Results will appear here when you interact with the samples.

Open a dialog with no handler

SetCommandFor

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.

C#
<button @ref="_invoker">Open</button>
<dialog @ref="_dialog"></dialog>

await invokerCommands.SetCommandFor(_invoker, _dialog, "show-modal");
Live sample

A real <dialog>, opened by the browser.

dialog output
Results will appear here when you interact with the samples.

Custom commands

OnCommand

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.

C#
_sub = await invokerCommands.OnCommand(_panel, args =>
{
    if (args.Command == "--refresh") Reload();
    InvokeAsync(StateHasChanged);
});

await invokerCommands.SetCommandFor(_refreshButton, _panel, "--refresh");
Live sample
Target panel Commands received: 0
command output
Results will appear here when you interact with the samples.

API reference

Member
Signature
Description
IsSupported
ValueTask<bool> IsSupported()
True when the runtime implements command/commandfor and CommandEvent.
SetCommandFor
ValueTask<bool> SetCommandFor(ElementReference invoker, ElementReference target, string command)
Points an invoker at a target and says what it does. The invoker must be a <button>.
ClearCommandFor
ValueTask<bool> ClearCommandFor(ElementReference invoker)
Unpoints an invoker, so it stops acting on anything.
GetCommand
ValueTask<string> GetCommand(ElementReference invoker)
The command an invoker currently carries, or an empty string.
OnCommand
Task<ButilSubscription> OnCommand(ElementReference target, Action<CommandEventArgs> handler)
Listens for commands dispatched at an element. Built-in ones have already been carried out by the time the handler runs.
DisposeAsync
ValueTask DisposeAsync()
Detaches every listener registered through this instance and releases its interop reference.
An unhandled error has occurred. Reload 🗙