Web-Komponenten mit Angular Elements
Geschrieben am von ih
Inhaltsverzeichnis
Navigation überspringen- Was sind Webkomponenten?
- Erstellung des Angular-Projektes
- Umwandlung des Projektes in eine Web-Komponente
- Einbindung der Webkomponente
Webkomponenten - Wieso?
Am Anfang meiner Karriere wir haben wir hauptsächlich mit Joomla gearbeitet; während der Zeit kamen diverse Sonderwünsche und eigene Ideen auf, die zur Entwicklung eigener Module für Joomla geführt haben. Im Laufe der Jahre haben sich allerdings weitere CMS wie Contao und Wordpress hinzugesellt, was uns vor das Problem stellte, dass der Code unserer Joomla-Module nur zum Teil für Module von anderen CMS übernommen werden konnte. Nicht nur das: mit jeder Portierung ist ein neues Projekt hinzugekommen, das gewartet und aktualisiert werden muss. Was also tun?
Hier kommen Webkomponenten in's Spiel. Diese sind plattformunabhängig und werden von jedem gängigen Browser unterstützt; keine Extrawurst pro CMS und nur noch ein Projekt das gepflegt werden muss! Da liegt der Gedanke doch nahe, das Modul in eine Webkomponente umzuwandeln.
Was sind Webkomponenten?
Web Komponenten sind eine Technologie die es Entwicklern ermöglicht, wiederverwendbare Elemente zu erstellen, deren Code abgekapselt von der eigentlichen DOM ausgeführt wird. Hierfür kommen die folgenden drei Technologien zum Einsatz:
Custom Elements
Mit Custom Elements können Entwickler ihre eigenen HTML-Tags und deren Funktionalitäten definieren.
Shadow DOM
Obschon Web Komponenten in der DOM auftauchen, werden diese effektiv innerhalb der Shadow DOM gerendert. Dieser DOM-Baum wird an die DOM angehangen, und sorgt dafür dass dessen Code abgekapselt vom restlichen Code des Dokumentes ausgeführt wird.
HTML-Templates & Slots
Mit Templates können wiederverwendbare Markup-Vorlagen erstellt werden, während der Inhalt dieser Vorlagen mittels Slots definiert werden kann.
Erstellung des Angular-Projektes
Im ersten Schritt muss selbstverständlich das Angular-Projekt angelegt werden. Dies funktioniert ganz einfach mit folgendem Befehl:
ng new <Projekt-Name> --no-standalone
Obwohl Angular Web Komponenten von sich aus unterstützt, werden die entsprechenden Bibliotheken bei einem neuen Projekt nicht automatisch hinzugefügt, sondern müssen mit folgendem Befehl installiert werden:
npm i @angular/elements
Nun ist das Projekt bereit, in eine Webkomponente umgewandelt zu werden.
Umwandlung des Projektes in eine Web-Komponente
app.module.ts
Im ersten Schritt wird die Datei app.module.ts angepasst. Die Klasse wird um den Angular-Hook DoBootstrap erweitert, und über den constructor wird ein injector hinzugefügt, mit dem unser Custom Element definiert wird.
Innerhalb des Bootstrap-Hooks ngDoBootstrap wird die Webkomponente definiert und zur Verfügbung gestellt; mit der createCustomElement-Funktion wird ein Custom Element auf Basis einer Angular-Komponente (in unserem Fall die AppComponent) erstellt, und mittels der customElements.define-Funktion wird definiert, mit welchem Tag die Web-Komponente in die DOM eingefügt werden kann. Bei der Benennung des Tags sind folgende Regeln zu beachten:
- Der Tag-Name muss mit einem kleingeschriebenen alphabetischen Zeichen (a-z) anfangen.
- Der Tag-Name muss mindestens einen Bindestrich (-) enthalten.
- Bereits existierende HTML-Tags können nicht als Tag-Name verwendet werden.
- Der Tagname darf keine Symbole enthalten. (=, @, $ usw.)
Auf dieser Seite von webcomponents.guide ist ein Tool zum Kontrollieren des Namens, ebenfalls sind die Namensregeln detaillierter aufgelistet.
export class AppModule implements DoBootstrap {
constructor(readonly injector: Injector) {}
ngDoBootstrap() {
const webArticle = createCustomElement(AppComponent, {
injector: this.injector,
});
customElements.define('web-article', webArticle);
}
}
Zum Abschluss muss noch die folgende Zeile entfernt werden, um den Angular-Fehler NG05104 zu verhindern:
bootstrap: [AppComponent]
Erweiterung der main.ts
Nach der app.module.ts muss nun noch ebenfalls die main.ts wie folgt angepasst werden, um den Angular-Fehler NG0908 zu verhindern:
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import 'zone.js';
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.error(err));
Die Webkomponente bauen
Damit die Kompoente benutzt werden kann, muss ein Build mit dem folgenden Befehl erstellt werden:
ng build --output-hashing none
Zu beachten ist das --output-hashing none
Standardmässig wird dem Dateinamen der generierten main-Datei nach jedem build ein neuer Hash hinzugefügt; da die Datei über ihren Namen importiert wird, sind Aktualisierungen leichter durchzuführen, wenn der Hash mit dem Flag nicht hinzugefügt wird.
Alternativ kann ebenfalls ein Script in der package.json angelegt werden.
Der generierte Code befindet sich nach dem Bauen in folgendem Pfad.
<Projekt-Verzeichnis>/dist/<Projekt-Name>/browser/main.js
Einbindung der Webkomponente
Eine Webkomponente wird mit den folgenden drei Schritten in eine Webpräsenz eingebunden:
- Die generierte main.js hochladen.
- Die main.js über das Script-Tag in die Seite einbinden.
- Die Webkomponente über das in der app.module.ts Tag an der gewünschten Stelle einfügen.
Allerdings wird jeder dieser Schritte je nach System etwas anders durchgeführt.
HTML5
Das Einbinden der Webkomponente auf einer statischen HTML5-Seite ist sehr einfach. Hier muss in der entsprechenden HTML-Datei ein Script-Tag im Head eingefügt werden, dessen src-Attribut den Pfad zur main.js . Anschliessend kann die Webkomponente in der gleichen Datei mit dem definierten Tag eingefügt werden:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Angular Social Feed</title>
<script src="web-article/dist/web-article/browser/main.js"></script>
</head>
<body>
<web-article></web-article>
</body>
</html>
Contao
Zum Verwenden von Web-Komponenten mit Contao wird die main.js über das UI in einen öffentlichen Ordner hochgeladen. Die Datei kann anschliessend über ein Seitenlayout (Themes -> Seitenlayouts) eingebunden werden mit dem Menpunkt Externe JavaScripts in die Seite eingebunden werden.
Damit ist die Webkomponente auf jeder Seite verfügbar, die dieses Layout benutzt. Anschliessend kann diese über ein Modul oder einen HTML-Block an einer beliebigen Stelle eingefügt werden.
Beim Einfügen via Inhaltelement sollte das Element Ungefiltertes HTML verwendet werden, da Contao die Klammern des Tags durch HTML-Entities ersetzen kann, wodurch lediglich der Name des HTML-Tags angezeigt wird.