Ab Chrome 135 werden für Buttons `command` und `commandfor` eingeführt
(developer.chrome.com)- Buttons sind essenziell für die Erstellung dynamischer Webanwendungen. Sie werden verwendet, um Menüs zu öffnen, Aktionen umzuschalten und Formulare abzusenden
- In Chrome 135 werden mit den neuen Attributen
commandundcommandfordie bisherigen Attributepopovertargetactionundpopovertargetverbessert und ersetzt - Probleme, die bisher bei der Implementierung von Button-Verhalten auftraten:
onclick-Handler in HTML können durch Sicherheitsrichtlinien (CSP) im produktiven Code nur eingeschränkt nutzbar sein- Der Status von Buttons und anderen Elementen muss synchronisiert werden, und Code zur Statusverwaltung bei gleichzeitiger Wahrung der Barrierefreiheit ist komplex
- Auch in React, AlpineJS, Svelte usw. ist das Handling von Status und Events komplex
Das Muster mit command und commandfor
- Mit den Attributen
commandundcommandforkönnen Buttons deklarativ auf andere Elemente wirken. Das bietet den Komfort von Frameworks und bleibt zugleich flexibel - Ein
commandfor-Button verwendet eine ID (ähnlich dem Attributfor), undcommandakzeptiert eingebaute Werte für einen intuitiveren Ansatz - Beispiel: Implementierung eines Buttons zum Öffnen eines Menüs
- Kein
aria-expandedoder zusätzliches JavaScript erforderlich
<button commandfor="my-menu" command="show-popover"> Open Menu </button> <div popover id="my-menu"> <!-- ... --> </div> - Kein
command und commandfor vs. popovertargetaction und popovertarget
- Wenn du
popoverbereits verwendet hast, kennst du vielleicht die Attributepopovertargetundpopovertargetaction - Diese funktionieren ähnlich wie
commandforundcommand, sind aber auf Popovers spezialisiert - Die neuen Attribute ersetzen die bisherigen vollständig und bieten zusätzliche Funktionen
Eingebaute Befehle
- Das Attribut
commandenthält eingebaute Aktionen, die verschiedenen APIs zugeordnet werdenshow-popover: wird aufel.showPopover()abgebildethide-popover: wird aufel.hidePopover()abgebildettoggle-popover: wird aufel.togglePopover()abgebildetshow-modal: wird aufdialogEl.showModal()abgebildetclose: wird aufdialogEl.close()abgebildet
- Beispiel: Implementierung eines Bestätigungsdialogs zum Löschen
- Status- und Barrierefreiheitsverwaltung sind ohne JavaScript möglich
<button commandfor="confirm-dialog" command="show-modal"> Delete Record </button> <dialog id="confirm-dialog"> <header> <h1>Delete Record?</h1> <button commandfor="confirm-dialog" command="close" aria-label="Close"> <img role="none" src="/close-icon.svg"> </button> </header> <p>Are you sure? This action cannot be undone</p> <footer> <button commandfor="confirm-dialog" command="close" value="cancel"> Cancel </button> <button commandfor="confirm-dialog" command="close" value="delete"> Delete </button> </footer> </dialog>- Code zur Verarbeitung des Ergebnisses: Im
close-Event des Dialogs kann der Rückgabewert verarbeitet werden
dialog.addEventListener("close", (event) => { if (event.target.returnValue === "cancel") { console.log("Cancel was clicked"); } else if (event.target.returnValue === "delete") { console.log("Delete was clicked"); } });
Benutzerdefinierte Befehle
- Neben den eingebauten Befehlen können mit dem Präfix
--auch benutzerdefinierte Befehle definiert werden - Benutzerdefinierte Befehle lösen auf dem Zielelement das Event
"command"aus, führen aber keine zusätzliche Logik aus - Beispiel: Implementierung eines Befehls zum Drehen eines Bildes
<button commandfor="the-image" command="--rotate-landscape"> Landscape </button> <button commandfor="the-image" command="--rotate-portrait"> Portrait </button> <img id="the-image" src="photo.jpg"> <script type="module"> const image = document.getElementById("the-image"); image.addEventListener("command", (event) => { if (event.command === "--rotate-landscape") { image.style.rotate = "-90deg"; } else if (event.command === "--rotate-portrait") { image.style.rotate = "0deg"; } }); </script>
Befehlsverarbeitung im Shadow DOM
- Im Shadow DOM gibt es bei
commandfor, da es auf IDs basiert, folgende Einschränkungen:- Elementreferenzen zwischen Shadow-DOMs sind nicht möglich
- In diesem Fall kann über die JavaScript-API die Eigenschaft
.commandForElementgesetzt werden
- Beispiel: Verknüpfen eines Befehls im Shadow DOM
<my-element> <template shadowrootmode="open"> <button command="show-popover">Show popover</button> <slot></slot> </template> <div popover><!-- ... --></div> </my-element> <script> customElements.define("my-element", class extends HTMLElement { connectedCallback() { const popover = this.querySelector('[popover]'); this.shadowRoot.querySelector('button').commandForElement = popover; } }); </script>
Zukünftige Pläne
- Chrome plant die Einführung weiterer eingebauter Befehle:
- Öffnen und Schließen von
<details>-Elementen - Unterstützung des Befehls
show-pickerfür<input>und<select> - Wiedergabebefehle für
<video>und<audio> - Funktion zum Kopieren von Text aus Elementen
- Öffnen und Schließen von
1 Kommentare
Hacker-News-Kommentare
Programmiersprachentheoretiker spekulieren seit den 80ern über "comefrom", eine mächtigere Version von "goto". Implementiert wurde das nur in intercal. intercal ist in Sicherheit, Performance und Ergonomie Sprachen wie C überlegen, hat aber Schwierigkeiten, in den kommerziellen Markt vorzudringen. Es ist interessant zu sehen, wie JavaScript dieses Feature von intercal übernimmt. Hoffentlich führt das zu einem Aufschwung des höflichen Programmierens, so wie die auf Closures basierenden Objekte von JavaScript funktionale Programmierung in den Mainstream gebracht haben
Invokers sind nicht nur eine Chrome-Sache. In Firefox Nightly sind sie ebenfalls bereits verfügbar
Die Idee, deklaratives UI-Verhalten ohne JS zu implementieren, ist attraktiv
aria-expandedist nicht nötig)show-modalintegrieren Accessibility direkt ins Markup--rotate-landscape) ermöglichen es Komponenten, ihre API über HTML bereitzustellenFragen:
.commandForElementüber Shadow Roots hinweg zu setzen, ist JS nötig. Das wirkt wie ein nur halb gelöstes Problemshow-picker,toggle-details), bläht sich die Plattform dann mit Nischen-Syntax auf?Spezifikation:
button-Element,commandfor-Attributbutton-Element,command-AttributIst das das Action-/Messaging-Pattern, das NeXT, Be, Apple usw. vor etwa 30 Jahren verwendet haben, oder übersehe ich etwas?
Netscapes frühes Java-UI-Toolkit (IFC) ermöglichte es, Action-Elemente zu verdrahten
Die neuen Attribute
commandundcommandforverbessern und ersetzenpopovertargetactionundpopovertargetIch habe eine regelrechte Allergie gegen Programmierung mit Strings. Ich verstehe die Accessibility-Vorteile, bin aber nicht besonders begeistert davon, Element-IDs als weitere Verhaltensschicht für Web-Apps zu verwenden
Das hätte nicht ohne die vollständige API implementiert werden sollen. Statt etwa fünf Befehlen wirkt es so, als könnte man über HTML die gesamte JavaScript-Funktionalität abbilden. Das wären Tausende von Befehlen
Ich hatte in HTML eher auf "command and conquer" gehofft
Es ist gut, HTML zu verbessern und zu erweitern, aber es ist noch ein weiter Weg. Das HTMX-Team hat einige gute Ideen