Mit der letzten Angular-Version 17 läutete das Angular-Team ein neues Zeitalter des Frameworks ein – wie sie es selbst nennen, die “Renaissance”. Aber auch mit den vorhergehenden Versionen wurden zahlreiche Dinge modernisiert und davon blieb auch die hauseigene Komponentenbibliothek “Angular Material” nicht verschont. Die wohl umfangreichste und gravierendste Änderung ist der Umbau aller Komponenten auf den MDC-Standard. Mit Version 15 wurden die alten Komponenten in den Legacy-Status verschoben und mit Version 17 endgültig erneuert. Während diese Änderungen vielen Nutzern das Leben erleichtert haben, verursachten sie bei manchen auch erhebliche Kopfschmerzen während des Updates. In diesem Artikel wird die Entwicklung des Angular Material Frameworks thematisiert und dabei erklärt, wie es überhaupt zu diesen Aufwänden und Problemen gekommen ist und auf was es ankommt, damit das in Zukunft nicht mehr passieren wird.
- Software-Modernisierung
Angular 15+ Upgrade: eine Checkbox, die es in sich hat
Die wohl umfangreichste und gravierendste Änderung ist der Umbau aller Komponenten auf den MDC-Standard. Mit Version 15 wurden die alten Komponenten in den Legacy-Status verschoben und mit Version 17 endgültig erneuert. Während diese Änderungen vielen Nutzern das Leben erleichtert haben, verursachten sie bei manchen auch erhebliche Kopfschmerzen während des Updates.
Angular Material < 15 !== customizable
Wer in der Vergangenheit schon mit der Komponentenbibliothek Angular Material gearbeitet hat, weiß vielleicht, dass die Anpassbarkeit der Komponenten nicht gerade zu den Stärken der Bibliothek zählt. Ab einem gewissen Anpassungsgrad arbeitet man mehr gegen das Framework als mit dem Framework. Eine auf den ersten Blick trivial erscheinende Anpassung erfordert Overrides im globalen Stylesheet oder die Verwendung des schon lange depreacteten CSS-Pseudoselektors “::ng-deep”. Unter Umständen ist einem auch gar nicht bewusst, welche Auswirkungen diese “Workarounds” langfristig haben, denn man hat ja erreicht, was man wollte. Zu welchem Preis stellte sich dann erstmals heraus, als Angular mit Version 15 die Migration der gesamten Material-Bibliothek auf den MDC-Standard veröffentlichte. Dankenswerterweise werden Angular Schematics mitgeliefert, mit deren Hilfe grundsätzlich alle Komponenten automatisch migriert werden können.
Voller Euphorie wird das Schematic ausgeführt und die Applikation kompiliert sogar noch. Yaay! Beim ersten Aufruf der migrierten Applikation erkennt der Kunde allerdings seine eigene Webanwendung nicht mehr wieder. Spätestens jetzt fällt die Entscheidung, die Komponenten großflächig anzupassen, dem Kunden auf den Kopf. Nun wurde kürzlich mit Angular 18 die Version 3 des Material Design Systems veröffentlicht und man möchte die damalige Erfahrung kein zweites Mal erleben.
Angular Material: Heute (v15+)
Selbstverständlich möchten die meisten Unternehmen ihr “Corporate Design” in ihre Angular-Applikation(en) über die Farbgebung und Typografie hinaus integrieren. Das erkannte auch das Angular Material Team und setzte es sich zum Ziel, den Anpassungsgrad der Bibliothek zu erhöhen. Die Lösung: Design-Tokens statt fixe Eigenschaften. Mit diesen Tokens soll eine definierte API zur Anpassung der Komponenten geschaffen werden. Seit Version 15 werden die Komponenten laufend mit solchen Token erweitert und so erlangt das Framework immer mehr und mehr offiziell unterstützte Anpassungsmöglichkeiten. Vergleicht man die Dokumentation der Versionen 14 und 17, stellt man schnell fest, dass vorher hartcodierte Eigenschaften nun durch CSS-Variablen abgebildet sind, die den Wert der Eigenschaft beinhalten.
Beispiel: Eine “simple” Checkbox-Anpassung
Gefordert ist eine Checkbox mit einem türkisen Hintergrund und einem dunkelgrauen Häkchen, wie in der folgenden Abbildung zu sehen:
Man begebe sich 2 Jahre zurück in der Vergangenheit zur Version Angular 14, vor der Einführung der MDC Komponenten.
Die Checkbox Hintergrundfarbe anzupassen stellt kein Problem dar, denn sie leitet sich entweder von der Primary-, Accent-, oder Warnfarbe des Themes ab.
Auf den ersten Blick würde man meinen, die Anpassung der Häkchen-Farbe sei im Handumdrehen erledigt. Die Checkbox wird in das Template aufgenommen, die Entwicklerwerkzeuge im Browser des Vertrauens geöffnet und schnell ist die Klasse des Häckchen umgebenden Elementes ausfindig gemacht. Beim Versuch, die CSS-Eigenschaften dieser Klasse zu überschreiben, wird man rasch merken, dass dies doch gar nicht so einfach ist. Der Grund ist Angular’s ViewEncapsulation, denn diese unterbindet das Überschreiben von CSS-Eigenschaften innerhalb einer Komponente. Auf den zweiten Blick gestaltet sich also die Sache doch nicht so problemlos wie Anfangs vermutet.
Ein vorbildliches Mitglied des Entwicklungsteams wirft zunächst einen Blick in die Dokumentation, findet dort jedoch keinen beschriebenen Ansatz für diese Änderung. Auch die Entwicklerwerkzeuge des Browsers liefern keine Ergebnisse, da dort kein leicht anpassbares Token zu finden ist.
Einfach aufgeben ist natürlich keine Option. “Die Checkbox muss einfach so aussehen, das kann doch nicht so schwierig sein!”, denkt man sich und landet im nächsten Moment schon auf Stackoverflow, wo man vermehrt Lösungen findet, die einem spätestens beim besagten MDC-Update auf den Kopf gefallen sind.
Vermutlich hat jede:r von uns schon mal einen Code in diese Richtung geschrieben, wo wir mittlerweile den Kopf schütteln würden. Uns interessiert aus heutiger Sicht aber folgendes: Wussten wir es damals einfach nicht besser oder gab es wirklich keinen anderen Weg…?
Ein Blick in den Source Code vor dem MDC-Update
Folgender Code ist für die Farbe des Häkchens verantwortlich:
Die Farbe ist also auf den ersten Blick nicht hartcodiert definiert, sondern kommt von der background-Farbpalette. Nun wäre es noch interessant, wie diese entsteht. Das dokumentierte und bekannte SCSS Mixin “define-light-theme”, das für die Erstellung eines eigenen Themes benötigt wird, nimmt für die Farbdimension nur drei Parameter entgegen, die jeweils eine Farbpalette abbilden: primary, accent und warn. In den Tiefen der internen Funktionen findet sich dann schließlich diese Stelle:
Wenn man jetzt noch genau auf die hier referenzierte Farbpalette $light-theme-background-palette schaut, wird man feststellen, dass spätestens dort die Farbe doch hartcodiert ist, denn das Checkbox Häkchen wird schlussendlich die Farbe “#fafafa“ (Hue 50) von der “light-theme-background-palette” annehmen. Solche Patterns findet man auch in vielen anderen Komponenten. Doch Achtung! All das in diesem Abschnitt gezeigte gilt als “Private Implementation Detail“ und sollte nicht dazu verleiten, die Farbpalette in irgendeiner Art und Weise zu überschreiben. Schlussendlich kann sich die interne API jederzeit ändern. Mal ganz abgesehen davon, dass die Lösung sogar weitaus komplexer wäre, als die CSS-Klasse zu überschreiben.
Tokens zur Rettung!
Beenden wir die Zeitreise und begeben uns wieder in die Gegenwart. Mittlerweile sind solche Anpassungen kein Problem mehr. Wie bereits im vorherigen Kapitel erwähnt, werden seit Angular 15 laufend Tokens eingeführt, so auch für die Farbe des Checkbox-Häkchens. Glücklicherweise erzeugt Angular Material diese Token, die nichts anderes als CSS-Variablen sind. Sie sind einfach änderbar und laut Dokumentation genau dafür gedacht.
Die Lösung für das Beispiel der gewünschten Checkbox Anpassung ist somit nun sehr simpel:
Außerdem leitet sich seit Angular Material 17.2 die Häkchen Farbe von der Kontrastfarbe der gewählten Farbpalette ab:
Die Variante mit dem Token wäre in diesem Beispiel zu bevorzugen, da die Türkise Farbe benötigt wird und die Kontrastfarbe in der Palette hauptsächlich für Texte gedacht ist.
Ausblick: Material 3
Durch die Token-basierte Theming API öffnet das Angular Material zunehmend die Tore der Komponenten und ermöglicht damit einfache Anpassungsmöglichkeiten. Es steht auch zur Diskussion, dass die existierenden Token offiziell dokumentiert werden. Damit könnten in Zukunft also UI/UX-Designer:innen und Entwickler:innen viel besser zusammenarbeiten, da die Designer:innen beim Entwurf bereits berücksichtigen können, welche Anpassungen überhaupt möglich sind. Das würde schon in der Konzeptionsphase “unlösbare” oder nicht nachhaltige Designentscheidungen verhindern, da man sich bestenfalls darauf einigt, nur solche Anpassungen vorzunehmen, welche durch die API bzw. die Token abgedeckt sind. Darüber hinaus wird mit Version 3 des Material Design Systems, welches gerade eben mit Angular 18 veröffentlicht wurde, die API nochmal verbessert und Angular Material als Design Systems noch ein Stück flexibler.
Fazit
Retrospektiv betrachtet war es vielleicht gar nicht so schlecht, dass durch das MDC-Update so viel auf den Kopf gestellt wurde. Möglicherweise wurde bei allen Betroffenen ein Bewusstsein geschaffen, dass man mit manchen CSS-Hacks aufpassen muss, speziell, wenn diese interne CSS-Klassen anzielen. Die Erkenntnis wird bei den meisten wohl gewesen sein, dass man so nah wie möglich am Standard bleiben sollte, wenn man sich für ein Komponenten-Framework wie Angular Material entscheidet.
Wir hoffen, dass der Aufwand der Umstellung vielleicht auch beim Management und auf fachlicher Ebene angekommen ist, sodass in Zukunft keine zu gravierenden Anpassungen mehr angefordert werden. Oft können die Entwickler schließlich nichts dafür, wenn solche Veränderungen umzusetzen sind. Im Zweifelsfall lohnt es sich auf jeden Fall, einen Blick auf Angular CDK zu werfen, denn hier kann man vorhandene Funktionalitäten nutzen und sich selbst um das Styling kümmern, wenn es nötig ist. Wir sehen die Veränderungen von Angular Material als sehr positiv an und freuen uns darauf, unsere Kunden bei dem kommenden Update auf Material 3 zu unterstützen und unsere Erfahrungen zu teilen.