ANGULAR ELEMENTS

Schritt-für-Schritt-Anleitung, um eine Angular-Komponente als natives Custom-Element zu exportieren

Entstehung des Custom-Elements aus Angular-Komponente!

Angular-Elements sind Angular-Komponenten, die als Custom-Elements verpackt sind. Dies bietet die Möglichkeit, Angular-Komponenten in nicht-Angular-Umgebungen zu verwenden.

Es gibt einige gute Gründe, Angular-Elements zu verwenden. Der größte, meiner Meinung nach, ist die Wiederverwendbarkeit. Das heißt, Du kannst Angular-Komponenten in anderen Frameworks und Bibliotheken wie React, Vue und Ember verwenden.‍ Außerdem kannst Du mit Angular-Elements auch Teile Deiner Anwendung unabhängig voneinander entwickeln und veröffentlichen. Es gibt noch viele weitere Bereiche, in welchen Angular-Elements sehr nützlich seinkönnen. Diese stellt Rob Wormald in seinem Vortrag auf der ng-conf 2018 vor.

WEB-COMPONENTS

Custom-Elements, Shadow DOM und HTML-Templates — sind drei Haupt-Web-APIs der Web-Components, die gemeinsam oder getrennt eingesetzt werden können.

CUSTOM-ELEMENTS

Custom-Elements ist eine der Web-Technologien, welche unter den Web-Component Technologien zusammengefasst werden. Mit der Custom-Elements-API, ist es es möglich eigene HTML-Elemente zu erstellen.

Wie auch “normale” HTML-Elemente, besitzen selbst erstellte Elemente (die Custom-Elements) Attribute, Eigenschaften, Methoden und können Events auslösen. Das von Dir erstellte Custom-Element kannst Du dann an einer beliebigen Stelle auf Deiner Webseite wiederverwenden.

Photo by Joe Caione on Unsplash‍

LET’S CODE! 🎉

Unsere Todo-Liste, um sich in dieser Anleitung nicht zu verlieren. Diese Liste werden wir nach jedem Kapitel aktualisieren:‍

⬜️ Erstellen und Set-Up des Angular Projekts

⬜️ Angular-Komponente erstellen

⬜️ Angular-Komponente in ein Custom-Element konvertieren

⬜️ Custom-Element als js-Datei exportieren

⬜️ Custom-Element verwenden und testen

1 Erstellen und Set-Up des Angular Projekts

1.1 Angular CLI einrichten

Angular-Elements wurden mit Angular 6 eingeführt. Es muss also auch die Angular CLI in der Version 6 oder höher installiert sein.

🧸 Hast du noch keine Angular CLI installiert?

Ich kann Dir den Blog-Post Starting an Angular App with Angular CLI in a couple of minutes empfehlen.‍

🧸 Hast Du bereits die Angular CLI installiert?

Überprüfe Deine Version:

▶ ng — version

Aktualisiere Deine Angular CLI, falls notwendig::

▶ npm uninstall -g angular-cli

▶ npm cache clean oder npm cache verify (wenn npm > 5)

▶ npm install -g @angular/cli@latest

1.2 Neues Projekt anlegen

Mein Angular-Projekt habe ich genannt 🚀. Hier ist der Befehl dafür:

▶ ng new angular-cosmic-elements

wobei “angular-cosmic-elements” der Projektname ist.

Nachdem Du erfolgreich Dein Projekt erstellt hast, gehe in den erstellten Projektordner und führe da alle weiteren Befehle aus.

1.3 Erforderliche Pakete installieren

Das Angular-Elements-Paket müssen wir separat installieren:

▶ ng add @angular/elements

Der oben genannte Befehl fügt unter Anderem das Polyfill document-register-element hinzu. Dies dient der Unterstützung von Browsern ohne nativer Custom-Elements Unterstützung.

‍‍✅ Erstellen und Set-Up des Angular Projekts

⬜️ Angular-Komponente erstellen

⬜️ Angular-Komponente in ein Custom-Element konvertieren

⬜️ Custom-Elements als js-Datei exportieren

⬜️ Custom-Element verwenden und testen

Damit ist unser Projekt nun bereit für den nächsten Schritt.‍

2 Angular-Komponente erstellen

Lass uns eine Komponente erstellen, die am Ende als Custom-Element verwendet werden kann! Der Befehl dafür lautet wie folgt:‍

▶ ng g component cosmic-button

Hierbei ist “cosmic-button” der Name unserer neuen Komponente.

2.1 CSS-Styles und Angular-ViewEncapsulation

Ein wichtiger Aspekt von Web-Components ist die Kapselung. Diese kann die Markup-Struktur, Styles und Events vor anderen Code-Abschnitten auf der Webseite verbergen. Damit können verschiedene Teile der Webseite nicht miteinander kollidieren und der Code bleibt schön und sauber. Die Shadow-DOM-API ist dabei ein wesentlicher Bestandteil. Mehr dazu findest du hier.

Das heißt, mit der Shadow-DOM-API können wir einer Komponente eigene Styles spendieren, ohne dass diese in die Außenwelt übergehen und sich auf fremden Komponenten auswirken. Deine Komponente wird auch vor dem Einfluss anderer Styles geschützt.

Das klingt doch toll, oder? 😎

In jeder Angular-Komponente befindet sich ein Decorator, der eine Eigenschaft namens encapsulation enthält. Bei dieser Eigenschaft kannst Du eine der folgenden ViewEncapsulation-Werten festlegen:

1〕

2〕

3〕

4〕

Angular 6 hat den neuen Wert ViewEncapsulation.ShadowDom (Shadow-DOM v1) eingeführt. Seitdem ist ViewEncapsulation.Native (Shadow-DOM v0) veraltet.
So kannst Du die ViewEncapsulation im Komponenten-Dekorator auf ShadowDOM v1 umstellen:

cosmic-button.component.ts

Mehr zu diesem Thema: ViewEncapsulations in Angular Component.

2.3 Angular und Shadow-DOM v1

Wir haben bereits die Kapselung für unsere Angular-Komponente auf ViewEncapsulation.ShadowDom festgelegt. Dadurch wird sichergestellt, dass die Komponente das native Shadow-DOM v1 (SD v1) verwendet. Wie Du auf dem folgenden Bild sehen kannst, wird diese Spezifikation leider nicht von allen Browsern unterstützt:

https://caniuse.com/#search=shadow%20dom

Mehr Informationen findest Du hier:

Angular 6.1 — ViewEncapsulation.ShadowDom

[Angular Elements] Supporting Shadow Dom and Theming IE11+

Shadow DOM v0 und v1

🧸 Was tun, wenn du einen Browser unterstützen musst, der SD v1 nicht unterstützt?

Als Alternative setzt Du die Komponenten-Eigenschaft ViewEncapsulation.ShadowDom auf

Mit dem “Emulated”-Wert wird kein Shadow-DOM verwendet. Stattdessen emuliert Angular das Shadow-DOM-Verhalten und isoliert die Komponenten-Styles. Dies bedeutet, dass Du auch in Browsern ohne Shadow DOM-Unterstützung Angular-Komponente verwenden kannst. In diesem Modus können die Angular-Komponenten und daraus erstellte Custom-Elements jedoch weiterhin die globalen Styles erben. Dies kann dazu führen, dass die Seite auf welcher man sein Element eingebettet, die Styles deiner Komponente (auf meist unerwünschte Weise) beeinflussen können.

Für IE9, IE10, IE11, und Chrome <55 musst Du zusätzlich weitere Polyfills aktivieren. Das erreichst du mit dem entkommentieren folgender Zeilen in der Datei polyfills.ts.

polyfills.ts

2.4 Lass uns die Angular-Komponente mit Leben füllen!!!

Ich will, dass mein Custom-Element (Cosmic-Button) beim Klicken seine Farbe umtauscht:

Um dies zu erreichen, mache ich folgendes:

1〕Alle nötigen Komponenten-Variablen hinzufügen.

2〕Eine Methode erstellen, die beim Klick-Event ausgelöst wird.

3〕In der Methode den Variablenwert toggeln, um die Farbe zu tauschen.

Schauen wir uns als Erstes mein HTML-Template von der Angular-Komponente an:

cosmic-button.component.html

Bei einem (click)-Event wird die onCosmicBtnClick()-Methode aufgerufen. In dieser toggeln wir die isHighlighted Variable. Dadurch wird wiederum im [ngStyle]-Attribut die Farbe ausgetauscht.

Um diesen Farbtausch zu ermöglichen, benötige ich zwei Farbvariablen: highlightColor und backgroundColor. Dazu noch eine boolean-Variable: isHighlighted, die beim Klicken auf true oder false gesetzt wird. Je nachdem ob isHighlighted true oder false ist, wird die Hintergrundfarbe des Buttons den highlightColor oder backgroundColor-Wert bekommen.

So sieht es in der Komponentendatei jetzt aus:

cosmic-button.component.ts

Im oberen Bild kannst Du sehen, dass ich die isHighlighted-Variable als normal Klassenvariable und alle anderen mit @Input annotiert habe. Letzteres ist dazu gedacht, Text und Farben des zukünftigen Custom-Elements als Attribut ändern zu können. Außerdem weise ich allen Inputs bereits einen eigenen Standardwert zu. So muss ich später nur die Attribute übergeben, welche ich auch wirklich anpassen möchte.

Um Custom-Events auszuprobieren, erstelle ich zusätzlich eine @Output-Variable “action”. Über den Event emitter können wir dann unsere Eigenen events auslösen. In meinem Fall passiert das bei jedem Klick auf den Button.

In meinem Custom-Event wird jedes mal auch der Wert von isHighlighted emitet:

cosmic-button.component.ts

So sieht meine komplette Cosmic-Button-Komponente aus:

cosmic-button.component.ts‍

Ich habe auch eine Style-Klasse für meine Angular-Komponente angelegt:

cosmic-button.component.scss‍

Um meine Angular-Komponen im Browser testen zu können, übergebe ich in der Datei app.module.ts dem bootstrap-Array die Cosmic-Button-Komponente.

app.module.ts

Mit dem ng serve Befehl baue und starte ich nun mein Angular-Projek:

▶ ng serve

Im Browser unter localhost:4200 kann ich meine Angular-Komponente nun ausprobieren:

2.5 Verarbeitung von Daten und Events

Wenn Deine Angular-Komponente in ein Custom-Element konvertiert wird, werden dabei @Inputs() zu Custom-Element-Attributen (siehe dazu attributeChangedCallback-Hook) und @Outputs zu Custom-Events. Folgende Namensformatierungen sind dabei zu beachten:‍‍

🐻 Input-Namen wie z.B. @Input() textColor werden in text-color konvertiert, um sie mit Custom-Elements kompatibel zu machen. Das heißt, die camelCase Schreibweise wird mit der kebab-case Schreibweise ersetzt.

☝︎ Groß- und Kleinschreibung wird dabei nicht berücksichtigt.‍

🐻 Output-Namen stimmen mit der Schreibweise von Custom-Events überein. Beispiel: Bei einer Komponente mit @Output() action löst das entsprechende Custom-Event mit dem Namen “action” aus. Gesendete Daten werden in der “detail”-Eigenschaft von Custom-Events gespeichert.

☝︎ Hier werden Groß- und Kleinschreibung unterstützt.‍

✅ Erstellen und Set-Up des Angular Projekts

✅ Angular-Komponente erstellen

⬜️ Angular-Komponente in ein Custom-Element konvertieren

⬜️ Custom-Elements als js-Datei exportieren

⬜️ Custom-Element verwenden und testen

Jetzt sind wir bereit unsere erstellte Angular-Komponente in ein Custom-Element zu konvertieren.

3 Angular-Komponente in ein Custom-Element konvertieren

Um eine Angular-Komponente in ein Custom-Element zu konvertieren, sind folgende Schritte in app.module.ts erforderlich:

1〕Entferne das Standard-Bootstrap-Array, mit AppComponent als Element.

2〕Füge Deine Angular-Komponente dem entryComponents-Array hinzu.

3〕Nutze ngDoBootstrap() für ein manuelles Bootstrapping.

app.module.ts

4〕Mit dem @angular/elements Paket erhältst Du Zugriff auf die Funktion createCustomElement(), mit der wir Custom-Elements aus einer beliebigen Angular-Komponente erstellen können. Erstelle eine Custom-Element-Klasse in der ngDoBootstrap-Methode:

app.module.ts

5〕Jetzt können wir das Custom-Element definieren und registrieren. Andernfalls wird es vom Browser nicht als solches erkannt. Dies erfolgt durch das Aufrufen von customElements.define():

app.module.ts

✅ Erstellen und Set-Up des Angular Projekts

✅ Angular-Komponente erstellen

✅ Custom-Element erstellen

⬜️ Custom-Element als js-Datei exportieren

⬜️ Custom-Element verwenden und testen

Nachdem wir unser Custom-Element definiert haben, bleibt uns nur noch, es zu exportieren. Dies wird uns ermöglichen, das Custom-Element in Nicht-Angular-Umgebungen zu verwenden.

4 Custom-Element als js-Datei exportieren

Bisher haben wir eine Angular-Komponente erstellt und in ein Custom-Element konvertiert. Jetzt müssen wir es exportieren, damit es auf beliebigen HTML-Seiten verwendet werden kann.

4.1 Dein Custom-Element für den Rest der Welt!

Normalerweise führen wir den Befehl ng build — prod aus, um die Angular-Anwendung zu bauen. Als Ausgabe erhalten wir einen dist-Ordner mit den gebündelten JavaScript-Dateien (runtime.js, scripts.js, polyfills.js und main.js). Wir werden aber unseres Custom-Element als einzelne Bundle-JS-Datei exportieren.

Als Erstes müssen wir das Hashing von Dateinamen deaktivieren, indem wir den “build”-Befehl in package.json unter “scripts” folgendermaßen anpassen:

▶ “build”: “ng build — prod — output-hashing=none”

‍Nach diesem befehl werden JS-Dateinamen im dist-Ordner kein Hashwert enthalten:

Mit und ohne — output-hashing‍

Als Zweites müssen wir einen “package”-Befehl innerhalb von “scripts” hinzufügen:

▶ “package”: “cat ./dist/angular-cosmic-elements/{runtime,polyfills,scripts,main}.js > custom-cosmic-button.js && ls -lah custom-cosmic-button.js”

☝︎ für Windows Benutzer: Windows unterstützt den “cat”-Befehl nicht. Daher kannst stattdessen jscat installieren und in obigem Befehl cat mit jscat ersetzen.

Nun noch alles speichern und die Komponente mit diesem Befehl bauen:

▶ npm run build

Abschließend alles nötige in einer Datei zusammenfassen:

▶ npm run package

Der letzte Befehl generiert eine einzelne unabhängige JavaScript-Datei mit unserem Custom-Element zum Einbetten auf beliebigen HTML-Seiten. Bei mir ist es die Datei namens custom-cosmic-button.js.

custom-cosmic-button.js‍

‍✅ Erstellen und Set-Up des Angular Projekts

✅ Angular-Komponente erstellen

✅ Custom-Element erstellen

✅ Custom-Element als js-Datei exportieren

⬜️ Custom-Element verwenden und testen

‍Bisher haben wir unsere Angular-Komponente in ein Custom-Element konvertiert und als eine JS-Datei exportiert. Jetzt ist die Zeit endlich gekommen, unser Custom-Element im Browser auszuprobieren!

5 Custom-Element verwenden und testen

5.1 Unser Custom-Element auf einer HTML-Seite verwenden

Erstellen wir einen neuen Ordner mit dem Namen “cosmic-website” und gleich auch in diesem neuen Ordner eine Datei namens index.html. Kopiere die vorherig generierte JS-Datei mit unserem Custom-Element in den neuen “cosmic-website”-Ordner.

Unser Custom-Element …

1〕…. erst importieren 🙃

in die HTML-Datei einfügen und anschließend die eben kopierte exportierte JS-Datei importieren.

2〕… html tag verwenden 🙌

Um das erstellte Custom-Element zu verwenden, musst Du dein Custom-Element-Tag, bei mir ist es <custom-cosmic-button></custom-cosmic-button>.

☝︎ Um Performance- und Lade-Probleme zu vermeiden, füge dein script-Import am Ende des <body>-Tags hinzu.

index.html

‍Speichere Deine Änderungen und öffne die Datei index.html im Browser. Wenn alles in Ordnung ist, wird das Custom-Element genau wie die Angular-Komponente im Teil aussehen.

Ich habe doch meine Angular-Komponente mit einigen @Inputs versehen (siehe den 2.4 Teil). Lass uns in der index.html diese Attribute verwenden:

index.html

So sehen dann meine Änderungen im Browser aus:

Nun möchte ich noch das Custom-Event des custom-cosmic-button tags testen. Dafür habe ich ein kleines Skript geschrieben und es auch am Ende des <body>-Tags hinzugefügt.

Ich verwende darin die addEventListener()-Methode meines Custom-Elements. Die übergebene Funktion wird ausgelöst, wenn man auf den Cosmic-Button klickt. Der addEventListener()-Methode übergebe ich auch ‘action’, als den Event-Typ für den wir uns interessieren ( siehe den 2.4 Teil, @Output-Variable in Angular-Komponente):

index.html

Mein EventListener gibt nun bei jedem “action”-Event eine Log-Meldung mit dem aktuellen Wert der “isHighlighted”-Variable aus. Das Ergebnis sieht dann (mit geöffneter Browser-Konsole) so aus:

5.2 Mögliche Browserfehler

Im Teil 1.3 “Erforderliche Pakete installieren“ haben wir das Polyfill document-register-element (DRE) zum Projekt hinzugefügt. Bei diesem Polyfill kann folgendes Problem im Browser auftreten:

🍄 Folgende Maßnahmen könnten dir mit dem Problem weiterhelfen:

1〕Die Version von document-register-element auf Version 1.8.1 zu ändern (issue-comment-dre-1.8.1):

‍▶ npm i document-register-element@1.8.1

2〕Überprüfe “target” in tsconfig.json. Es sollte auf ES5 gesetzt sein (issue-comment-target-es5).

🍄 Falls Du eine ältere Browserversion besitzt, könnte Dir das @webcomponents/webcomponentsjs Pollyfil helfen (Failed to construct ‘HTMLElement’ after updating to 4.0.1-issuecomment):

▶ npm install @webcomponents/webcomponentsjs

Außerdem musst Du folgende JS-Bibliothek am Ende der polyfills.ts-Datei hinzufügen:

5.3 Test mit einem lokalen HTTP-Server

Um unser Custom-Element auszuprobieren, werden wir einen einfachen lokalen HTTP-Server starten.

SimpleHTTPServer Python

Folgenden Befehl im Ordner mit der Ziel-Webseite (bei mir ) ausführen und dann mit http://127.0.0.1:8000 die Test-Webseite im Browser öffnen und checken:

▶ python -m SimpleHTTPServer

✅ Erstellen und Set-Up des Angular Projekts

✅ Angular-Komponente erstellen

✅ Custom-Element erstellen

✅ Custom-Element als js-Datei exportieren

✅ Custom-Element verwenden und testen

Und wir haben es geschafft! Jetzt kannst Du dieses Custom-Element in React.js, PHP, Vue.js und in jedem anderen Web-Framework verwenden!

‍‍Photo by Dušan Smetana on Unsplash

EPILOG! 🥁

Was haben wir so gemacht?

1〕Ein Angular-Projekt erstellt

2〕Das Angular-Elements Paket und Polyfill hinzugefügt.

3〕Eine Angular-Komponente erstellt.

4〕Die Angular-Komponente in ein Custom-Element konvertiert.

5〕Custom-Element als eine einzige JS-Datei exportiert.

6〕Custom-Element auf einer Webseite importiert und mit einem lokalen HTTP-Server ausgeführt und getestet.

MEHR ERFAHREN!

🦖 This blogpost is published by Comsysto Reply GmbH

comsystoreply

Innovation through insight.

comsystoreply

Innovation through insight. Thinking lean and moving agile when delivering software products for the digital era.

Nastia @ Comsysto Reply

Written by

👁 Kirikia, Artist, UX/UI Engineer working for Comsysto Reply GmbH

comsystoreply

Innovation through insight. Thinking lean and moving agile when delivering software products for the digital era.