Invoker Commands API
- html
- invoker
- javascript
Introduction
The Invoker Commands API addresses one of the key shortcomings of the HTML Dialog element—opening and closing without client-side JavaScript. It also introduces custom commands allowing developers to create their own actions that can be utilized from the command attribute.
Attributes
The command and commandfor attributes are the main controllers of the Invoker Commands API. The trigger element must have both of these attributes set in order for the command event to fire.
command- action to take upon clicking the trigger element, built-in or customcommandfor-idof the target element to execute the action on
As a best practice, also add the
type=buttonattribute to to any buttons that trigger commands to override the defaulttype=submit. This ensures accessibility and proper functionality within<form>elements.
Opening and closing dialogs
The Popover API has enabled developers to create popovers that open and close without the use of client-side JavaScript. The <dialog> element had been left behind until now, developers had to use the HTMLDialogElement.showModal and HTMLDialogElement.requestClose JavaScript methods.
With the Invoker Commands API, you can control dialog visibility without JavaScript. The command attributes mirror the instance methods adapted to kebab-case, for example show-modal and request-close.
<button commandfor="dialog-id" command="show-modal" type="button">
Show Dialog
</button>
<dialog id="dialog-id">
<h2>Dialog</h2>
<p>
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Magni
necessitatibus provident, totam vel a hic, numquam molestiae error doloribus
ab ducimus alias iste incidunt aliquid sint, inventore ea? Nihil,
perspiciatis?
</p>
<button commandfor="dialog-id" command="request-close" type="button">
Close
</button>
</dialog>
Popover API methods are also available as values for the command attribute, for example command=show-popover. See the full list of values here.
Custom commands
A powerful feature of the Invoker Commands API is custom commands. It unlocks some new patterns that make writing vanilla JS a bit more declarative. For example, we can switch the background color of the div with a custom --change-color command. Custom commands must be prefixed with --.
<button
type="button"
command="--change-color"
commandfor="content"
data-color="red"
>
Red
</button>
<button
type="button"
command="--change-color"
commandfor="content"
data-color="blue"
>
Blue
</button>
<button
type="button"
command="--change-color"
commandfor="content"
data-color="green"
>
Green
</button>
<div id="content"></div>
Instead of adding an event listener to the <button> elements, it can be added to the content instead. This makes it easy to create different commands for certain components that can be triggered from anywhere in your application via HTML attributes.
content.addEventListener("command", (e) => {
if (e.command === "--change-color") {
content.style.backgroundColor = e.source.dataset.color;
}
});
Self target
If you don’t need a separate target element, you can set the commandfor to target the trigger element with the same id. commandfor is required for the event to fire.
In most cases, if you are targeting the same element,
addEventListeneris probably a better option.
<button
command="--custom-command"
commandfor="self-id"
id="self-id"
type="button"
>
Self Target
</button>
Listening for any command
You can listen for all commands by adding an event listener to document.body with the capture option.
For example, you can log all command events on any element with the following code:
document.body.addEventListener(
"command",
(e) => {
console.log(e);
},
{ capture: true },
);
Conclusion
I’m interested to see how developers use this API when it’s supported across browsers. It could be a nice API to create a library of custom commands that users could access simply with HTML attributes.
Thanks for reading!