In einer Angular-Anwendung ist die Organisation des Codes von grundlegender Bedeutung, um eine wartbare, skalierbare und effiziente Architektur zu gewährleisten. Ein zentrales Konzept in Angular ist die Verwendung von Modulen, die den Code in logische Einheiten unterteilen, die getrennt geladen und verwaltet werden können. Diese Module können als Wurzelsystem oder als Feature-Module organisiert werden, wobei jedes Modul eine bestimmte Funktionalität innerhalb der Anwendung kapselt.
Ein Angular-Projekt kann nur ein Wurzelmodul haben, aber mehrere Feature-Module, die zusätzliche Funktionalitäten bieten. Diese Feature-Module sind dabei von zentraler Bedeutung, da sie es ermöglichen, die Anwendung in eigenständige, wiederverwendbare Teile zu unterteilen. Die Aufteilung des Codes in Module sorgt für eine bessere Organisation und ermöglicht es, die Anwendung effizienter zu laden, indem nicht alle Komponenten und Services zu Beginn geladen werden müssen. Stattdessen werden nur die Teile geladen, die für die aktuelle Ansicht erforderlich sind, was zu einer signifikanten Reduzierung der Ladezeiten führt.
Die Beziehung zwischen dem Wurzelmodul und den Feature-Modulen ist dabei eine Eltern-Kind-Beziehung. Ein Wurzelmodul kann einen Router enthalten, der wiederum Kind-Routen verwaltet. Diese Kind-Routen sind für das dynamische Nachladen von Feature-Modulen verantwortlich, was für die Implementierung von Lazy Loading entscheidend ist. Lazy Loading bedeutet, dass nur die Ressourcen und Module geladen werden, die für die aktuelle Ansicht benötigt werden, während andere erst bei Bedarf geladen werden. Dies reduziert nicht nur die anfängliche Ladezeit der Anwendung, sondern verbessert auch die Leistung, indem unnötige Daten und Assets vermieden werden.
Wichtig ist auch, dass in Angular Dienste (Services) standardmäßig als Singletons bereitgestellt werden. Das bedeutet, dass ein Service für ein ganzes Modul oder die gesamte Anwendung einmalig erstellt wird. Wenn jedoch der Service auf Modulebene oder Komponentenniveau bereitgestellt wird, können mehrere Instanzen dieses Services existieren, was zu Problemen bei der Dependency Injection führen kann. Ein solches Verhalten muss mit Bedacht eingesetzt werden, da mehrere Instanzen eines Services innerhalb einer Vererbungshierarchie zu unerwartetem Verhalten führen können.
Ein weiterer wichtiger Aspekt beim Entwerfen einer Angular-Anwendung ist das bewusste Management der Ladezeiten und der Performance. Wie Studien zeigen, verlassen 53% der mobilen Nutzer eine Webseite, wenn die Ladezeit 3 Sekunden überschreitet. Gerade auf mobilen Geräten, auf denen ein großer Teil des Datenverkehrs stattfindet, sind schnelle Ladezeiten entscheidend. Um diese zu erreichen, sollte man bei der Architektur der Anwendung von Anfang an Lazy Loading einplanen. So können beispielsweise Geschäftsbereiche oder Nutzerrollen als Feature-Module implementiert werden. Diese Module werden dann nur bei Bedarf geladen, was die Anwendung optimiert und die Benutzererfahrung verbessert.
Zu beachten ist hierbei, dass es wichtig ist, die richtigen Module für die Lazy-Loading-Strategie auszuwählen. So könnte man beispielsweise für unterschiedliche Nutzerrollen unterschiedliche Feature-Module definieren. Ein Daten-Entry-Spezialist würde nur eine eingeschränkte Anzahl von Funktionen benötigen, während ein Manager Zugang zu erweiterten Funktionen hat. Das bedeutet, dass für jede Nutzerrolle nur die relevanten Module geladen werden, was nicht nur die Ladezeiten verringert, sondern auch die Komplexität der Anwendung reduziert.
Ein wichtiger Punkt, der häufig übersehen wird, ist die Rolle des "Walking Skeleton" in der frühen Entwicklungsphase. Ein Walking Skeleton ist eine minimal funktionsfähige Version der Anwendung, die bereits ein grundlegendes Navigationssystem enthält. Diese Version hilft dabei, frühzeitig Feedback von Nutzern und Stakeholdern zu sammeln und grundlegende Integrations- und Arbeitsablaufprobleme zu identifizieren. Es ermöglicht außerdem mehreren Entwicklungsteams, gleichzeitig an verschiedenen Modulen zu arbeiten, ohne sich gegenseitig in die Quere zu kommen. Ein solches Vorgehen sorgt dafür, dass alle beteiligten Personen eine klare Vorstellung vom aktuellen Stand der Entwicklung und der geplanten Features haben.
Um eine wirklich skalierbare und wartbare Architektur zu entwickeln, ist es entscheidend, eine stateless, datengesteuerte Designstrategie zu verfolgen. Dies bedeutet, dass die Anwendung so strukturiert ist, dass sie ihren Zustand nicht intern speichert, sondern über externe, unveränderliche Datenquellen verwaltet wird. Ein solches Design fördert eine bessere Skalierbarkeit und Wartbarkeit, da es das Risiko von Fehlern und unerwartetem Verhalten verringert und die Arbeit mit Tools wie NgRx oder anderen State-Management-Lösungen erleichtert.
Die Implementierung von Lazy Loading und die Aufteilung der Anwendung in klare, modularisierte Einheiten stellt sicher, dass die Anwendung auch bei steigender Komplexität leistungsfähig bleibt und schnell auf die Bedürfnisse der Nutzer reagieren kann. Entwickler sollten dabei stets darauf achten, dass die Trennung von Funktionalitäten klar definiert ist und die Module so konzipiert werden, dass sie bei Bedarf nachgeladen werden können, ohne die Benutzererfahrung zu beeinträchtigen.
Wie man benutzerdefinierte Steuerungen in Angular-Formularen erstellt: Ein praktisches Beispiel
Die Erstellung benutzerdefinierter Formularsteuerelemente in Angular ermöglicht es, wiederverwendbare, modularisierte und anpassbare Eingabefelder zu implementieren. Diese Steuerelemente können für verschiedene Arten von Benutzereingaben verwendet werden, wobei ein gutes Beispiel die Implementierung eines "Lemon Rater" (Zitronenbewertungssteuerelements) darstellt. In diesem Kapitel wird Schritt für Schritt erklärt, wie ein solches Steuerelement in eine Angular-Anwendung integriert wird.
Zunächst wird ein neues Steuerelement namens LemonRaterComponent im Ordner user-controls erstellt. Dieses Steuerelement implementiert das ControlValueAccessor-Interface, das erforderlich ist, um das Steuerelement als benutzerdefiniertes Eingabefeld in Angular-Formularen zu integrieren. Das Interface sorgt dafür, dass die Interaktionen mit dem Steuerelement korrekt in den Formularwert übernommen werden.
In der Datei lemon-rater.component.ts wird das Interface wie folgt implementiert:
Dieses Beispiel zeigt, wie man das Steuerelement mit den notwendigen Funktionen ausstattet, um den Wert zu lesen und zu schreiben sowie auf Änderungen und Berührungen zu reagieren. Das Attribut writeValue sorgt dafür, dass der Wert des Steuerelements mit dem Formular synchronisiert wird, während registerOnChange und registerOnTouched dafür verantwortlich sind, dass das Steuerelement auf Änderungen im Formular reagiert.
Zusätzlich zur Implementierung des Interfaces müssen wir das Steuerelement bei Angulars Formularsystem registrieren. Dies geschieht mit dem NG_VALUE_ACCESSOR-Provider, der das Steuerelement an das Formular bindet:
In diesem Fall sorgt die multi: true-Eigenschaft dafür, dass das Steuerelement in das Formularsystem integriert wird und mehrere Provider für den gleichen Token verwendet werden können.
Der nächste Schritt besteht darin, eine benutzerdefinierte Bewertungslogik zu erstellen, die es dem Benutzer ermöglicht, eine Bewertung basierend auf seiner Auswahl festzulegen. Diese Logik wird in der Methode setRating implementiert:
Hierbei wird die Bewertung in einer internen Variable gespeichert, und sowohl der angezeigte Text als auch der Wert werden mit den Formularereignissen synchronisiert.
Zusätzlich wird der HTML-Code des Steuerelements so angepasst, dass der Benutzer beim Hovern oder Klicken auf die verschiedenen Bewertungsstufen visuelle Rückmeldungen erhält. Dies wird mit Hilfe von SVG-Elementen und CSS erreicht. Das Hover-Verhalten wird über CSS realisiert, indem das Aussehen der Sterne oder Zitronen beim Überfahren mit der Maus geändert wird:
Die CSS-Regeln sorgen dafür, dass sich das Aussehen der Steuerelemente dynamisch anpasst, wenn der Benutzer mit der Maus über die Elemente fährt oder sie auswählt.
Nachdem das Steuerelement vollständig implementiert ist, wird es in einem Formular verwendet. In diesem Fall wird der LemonRaterComponent in das Profil-Formular integriert, um den „Limoncu“-Level eines Mitarbeiters zu erfassen. Der Wert des level-Formularfeldes wird mit dem LemonRater synchronisiert:
In der HTML-Datei des Formulars wird das benutzerdefinierte Steuerelement als reguläres Angular-Formularsteuerelement eingebunden:
Auf diese Weise wird das benutzerdefinierte Steuerelement nahtlos in das Formular integriert, sodass es wie jedes andere Formularsteuerelement verwendet werden kann.
Ein weiterer Aspekt, den man beachten sollte, ist die Flexibilität von benutzerdefinierten Steuerelementen. Sie können für eine Vielzahl von Anwendungsfällen angepasst werden, und es gibt viele Möglichkeiten, sie zu erweitern. Zum Beispiel könnten zusätzliche Funktionen wie die Möglichkeit, benutzerdefinierte Bewertungsstufen hinzuzufügen, oder die Implementierung von animierten Übergängen beim Hover-Ereignis in Betracht gezogen werden.
Es ist auch wichtig zu verstehen, dass die Verwendung benutzerdefinierter Steuerelemente in Formularen die Wiederverwendbarkeit von Code fördert. Anstatt immer wieder dieselben Formularelemente zu schreiben, können Entwickler benutzerdefinierte Steuerelemente erstellen, die in verschiedenen Formularen und Anwendungen eingesetzt werden können. Dies spart nicht nur Zeit, sondern macht den Code auch übersichtlicher und wartungsfreundlicher.

Deutsch
Francais
Nederlands
Svenska
Norsk
Dansk
Suomi
Espanol
Italiano
Portugues
Magyar
Polski
Cestina
Русский