Februar 2024
Mit dem HTML-Element
template
kann HTML-Code in eine Seite für eine spätere Verwendung eingebettet werden. Ein Template wird im Browser nicht abgebildet, sein Inhalt kann aber mithilfe von JavaScript an anderere Stellen kopiert und damit sichtbar werden. Das kann in Abhängigkeit eines Ereignisses oder der Zeit passieren.
Siehe auch
MDN: Using templates and slots.
In diesen Beitrag fließen auch die Kenntnisse zu Shadow DOM und Custom Elements ein.
Ein Template für ein Custom Element
in den HTML-Bereich
<h3>Template mit Accordion</h3>
<template id="myTemplate">
<style>
b { color: #0066cc; font-size: 120%; }
</style>
<details>
<summary>
<b class="name">Begriff</b>
</summary>
<i>Erklärung</i>
</details>
</template>
<my-element></my-element>
Wenn wir das Dokument jetzt im Browser betrachten, würden wir die Überschrift sehen und sonst nichts.
Das leere
my-element
bietet ja auch nichts Sichtbares.
Das ändert sich aber sofort, wenn den Inhalt des Templates in das Element einbringen. Dazu platzieren wir folgenden Scriptcode in den Scriptbereich 2.
const myElement = document.getElementsByTagName('my-element')[0];
const templateInhalt = document.getElementById('myTemplate').content;
myElement.appendChild(templateInhalt.cloneNode(true));
Wichtig ist, die Methode cloneNode(true)
am Templateinhalt zu verwenden, sodass
wirklich eine Kopie des Inhalts und keine Referenz eingebracht wird.
Screenshot 1
Jetzt ist das details
-Element sichtbar, die Erklärung kann durch Anklicken des Markers
ein- oder ausgeblendet werden.
So ein Element könnte vielleicht an anderen Stellen auf der Seite auch gebraucht werden,
jedoch mit verschiedenen Inhalten.
Slots kommen ins Spiel
Eine Template-Kopie mit verschiedenen Inhalten kann über den Slot-Mechanismus realisiert werden.
In unserem Beispiel müssten
Begriff
und
Erklärung
ausgetauscht werden.
Dazu umhüllen wir die auszutauschenden Code-Teile mit
slot
-Elementen, die mit einem Namen
versehen werden müssen.
<template id="myTemplate">
<style>
b { color: #0066cc; font-size: 120%; }
</style>
<details>
<summary>
<b><slot name="Slot1">Begriff</slot></b>
</summary>
<slot name="Slot2"><i>Erklärung</i></slot>
</details>
</template>
Zuerst fügen wir zwei weitere Elemente des Typs my-element
hinzu als Zielelemente
des Templateinhalts.
In den Zielelementen bringen wir die konkreten Codeteile unter, die als Austausch dienen.
Das oberste Element des Austausch-Codes referenziert mit dem Attribut
slot
und dem entsprechenden Slotnamen, für welchem Slot es bestimmt ist.
<my-element>
<span slot="Slot1">Textfeld</span>
<input slot="Slot2" type="text" size="15">
</my-element>
<my-element>
<span slot="Slot1">Tabelle</span>
<table slot="Slot2" border="1">
<tr><th>A</th><th>B</th></tr>
<tr><td>Feld 1</td><td>Feld 2</td></tr>
</table>
</my-element>
<my-element></my-element>
So geht es jedoch nicht
Mit einer
for
-Schleife bringen wir den Templateinhalt in jedes der Zielelemente ein.
const list = document.getElementsByTagName('my-element');
const templateInhalt = document.getElementById('myTemplate').content;
for (let i = 0; i < list.length; i++)
{
let custElem = list.item(i);
// funktioniert nicht wie gewünscht
custElem.appendChild(template.cloneNode(true));
}
Das passiert auch, aber der Slot-Mechanismus funktioniert so gar nicht.
Effizienter mit registriertem Custom Element
Es ist nicht sonderlich effizient, vor jedem Einfügen eines Templateinhalts erst einen Shadow DOM aufzubauen. Auch auf die verwendete Schleife können wir verzichten, wenn wir aus unserem Customelement ein registriertes machen. Im folgenden Beispiel übernimmt die Definitionsklasse
myAccordion
sowohl das Anlegen des Shadow DOM als auch das Kopieren des Templateinhalts.
Nur noch das CustomElement registrieren - und weiterer Scriptcode wird nicht benötigt.
class myAccordion extends HTMLElement {
constructor() {
super();
const template = document.getElementById('myTemplate').content;
this.attachShadow({mode: 'open'});
this.shadowRoot.appendChild(template.cloneNode(true));
}
}
customElements.define('my-element', myAccordion);
So erklärt sich auch, warum Beispiele zu Shadow DOM, Custom Element, Template und Slot in bekannten Beispielen meistens miteinander kombiniert sind. Es war vielleicht ein wenig hilfreich, diese Mechanismen in mehreren Beiträgen mal einzeln zu durchleuchten, bevor wir sie fusioniert haben.
Ausblick
Es wird über weitere Vereinfachungen nachgedacht. Das Zauberwort heißt Deklarativer Shadow DOM
. So soll das Attribut shadowrootmode="open"
an <template>
bewirken, dass ein Shadow Root am Parent-Element des Templates eröffnet wird.
Schaun wir mal, wie sich das weiterentwickelt und was die Zukunft bringt.