Die Angular Chuck Norris Challenge ist dein erster Einstieg in die Angular Webapp Entwicklung. Erledige alle Challenges, damit Chuck Norris .. und die innFactory stolz auf dich sind! Im Rahmen des Projekts wirst du das Frontend einer 404 Not-Found Seite gestalten, mehr ĂŒber das Global State Management und die reaktive Programmierung in Angular erfahren, selbst eine Katzenbild-API anbinden und als Bonus Aufgabe deine Daten in einer selbst aufgesetzten, externen Datenbank speichern.
Jeder geschriebene Programmcode muss auch gespeichert und weitergegeben werden können. GitHub ist eine ĂŒbergreifende Entwicklerplattform die das ermöglicht und auch dieses Projekt speichert. Du wirst spĂ€ter nicht nur deinen Programmcode mit anderen Kollegen in Projekten teilen (=to publish), sondern in sogenannten Code-Reviews gegenseitig den Code ĂŒberprĂŒfen und verbessern. Code-Reviews wirst du beim Angular Chuck Norris Projekts noch nicht machen.
- Erstelle dir, falls du noch keinen hast, zunĂ€chst einen eigenen Github Account . Dieser wird dich bei der innFactory und im spĂ€teren Entwickler-Leben noch oft begleiten đ€©.
Softwareentwickler benötigen einen Ort an dem sie den Programmcode ansehen, schreiben und verĂ€ndern können. Dieser Ort ist die sogenannte Entwicklungsumgebung, auf englisch "Integrated Development Environment", abgekĂŒrzt IDE. FĂŒr die Angular Chuck Norris App benutzen du als IDE am Besten VS Code.
- Installiere dir Visual Studio Code.
- Ăffne VS Code. Mache dich mit diesem Tutorial in VS Code etwas vertraut.
In GitHub online gespeicherte Software muss zum Bearbeiten erst lokal auf deinem PC kopiert werden (=to clone). Das geht ebenfalls ganz einfach mit VS Code. VS Code kommt standardmĂ€Ăig mit einer Anbindung fĂŒr GitHub, dem "Source Control Management".
- Ăffne den Tab des Source Control und wĂ€hle "Clone Repository". Gebe nun die URL des Repositories
https://github.com/innFactory/angular-chuck-norris
ein und wÀhle einen beliebigen Speicherort auf deinem PC.
Die meisten Webapp Projekte haben AbhĂ€ngigkeiten an andere Bibliotheken in Form von Paketen. Diese können mit dem Node Package Manager von Nodejs unkompliziert installiert werden. Installiere dir hierfĂŒr nun Nodejs und fĂŒhre Node und NPM zum Test im Terminal in VS Code aus.
-
Installiere die Nodejs ĂŒber den Installer Nodejs Download.
-
PrĂŒfe ob die Befehle
node
undnpm
in deinem System global funktionieren. -
Ăffne dazu in VS Code das Terminal ĂŒber die obere Leiste
View -> Terminal
. -
Gebe im Terminal die folgenden Befehle ein. Nacheinander solltest du die aktuell installierte Version sehen.
node --version # Ausgabe z.B. "v22.18.0". npm --version # Ausgabe z.B. "10.9.3". npx --version # Ausgabe z.B. "10.9.3".
-
Mache dich ĂŒber die weiteren Funktionen von NPM vertraut https://docs.npmjs.com/about-npm.
Nun musst du dir die AbhĂ€ngigkeiten bzw. Dependencies nur noch installieren. Keine Sorge, die sind in der Datei package.json bereits vollstĂ€ndig aufgelistet und können ohne weiteres ĂŒber einen Konsolenbefehl installiert werden.
- Gebe in die Konsole
npm install
ein und und warte bis alle erfolgreich heruntergeladen sind. - Ein neuer Ordner node_modules/ mit allen externen Bibliotheken, wird nun im Projekt automatisch erstellt.
Nun kannst du das Webprojekt aus der Konsole starten mit npm start
.
-
Ăffne den Browser auf http://localhost:4200 und du solltest die Webapp sehen.
-
In der Konsole kannst du den laufenden, lokalen Client sehen.
~/code/intern/angular-chuck-norris npm start > [email protected] start > ng serve Initial chunk files | Names Raw size main.js main 116.17 kB styles.css I styles 10.13 kB | Initial total | 126.30 kB Application bundle generation complete. [2.387 seconds] Watch mode enabled. Watching for file changes... NOTE: Raw file sizes do not reflect development server per-request transformations. 10:03:05 AM [vitel (client) Re-optimizing dependencies because vite config has changed Local: http://localhost: 4200/ press h + enter to show help
Jede Angular Komponente in deiner Webapp besteht aus einem Logik-, einem Struktur- und einem Stylingteil. FĂŒhle dich nicht ĂŒberfordert von all den verschiedenen Sprachen und Frameworks. Du bekommst eine Schritt fĂŒr Schritt EinfĂŒhrung in die Angular Welt.
-
Sehe dir exemplarisch einmal die "AboutSection" Komponente genauer an. Navigiere in in den Pfad src/components/about-section/ und sehe dir die Dateien an.
Datei Function about-section.ts Logikteil in TypeScript about-section.html Strukturteil in HTML about-section.scss Stylingteil in SCSS -
SchlieĂe das interaktive Angular Einstiegs Tutorial im Browser ab. Nimm dir hierfĂŒr gerne etwas Zeit âïž.
Im Browser siehst du die Vorstellung von Chuck Norris. Weiter unten siehst du die "AboutSection". Dessen Struktur ist in der Markupsprache HTML verfasst. Im Folgenden erweiterst du diese bestehende Angular Komponente.
- Sieh dir die Struktur der "HomePage" src/pages/home/ und der darin eingebundenen "AboutSection" src/components/about-section/ einmal genauer an.
- Der Text "Ich bin Chuck Norris, ein Schauspieler und Kampfsportler.." ist in einem HTML
<p>
Paragraphen Element eingeschlossen bzw. gewrapped. So verfasst man Text in HTML. - Lese hier ĂŒber das Paragraphen Element auf der offiziellen HTML Dokumentation MDN Webdocs P Element
- Recherchiere auf diesem Wikipedia Eintrag ĂŒber Chuck Norris selbst erfundene KampfkĂŒnste und fĂŒge in der "AboutSection" weitere Fakten ĂŒber Chuck Norris hinzu. Die Ănderungen erscheinen beim Speichern automatisch im Browser.
FĂŒr jedes Framework und jede Sprache gibt es eine offizielle Dokumentation. Als Entwickler ist es am Besten, dich in der Doku deiner Sprache zurechtzufinden. Alle Neuerungen und Updates stehen hier immer zuerst.
- Ăberfliege die offizielle Angular Doku und bekomme einen ersten Ăberblick.
- Lese zum Einstieg auĂerdem folgende Angular-Artikel:
Angular hat eine eigene UI-Komponenten Bibliothek, die du optional verwenden kannst. Sie ermöglicht dir eine Auswahl an erweiterten Button, Input, Tabellen-Komponenten uvm. die du einfach einbinden kannst. Angular Material ist im Projekt bereits hinzugefĂŒgt und du kannst es einfach verwenden.
- Sieh dir die verfĂŒgbaren Angular Material Komponenten an.
- Um Angular Material Komponenten zu verwenden sind 3 Schritte wichtig. Hier das Beispiel der Dokumentation.
- Der Import ĂŒber "imports { ... } from 'angular/material/...";
- Die Angabe bei "imports: []" im Dekorator.
- Die Verwendung im HTML
TypeScript ist eine von Microsoft entwickelte Programmiersprache, die JavaScript erweitert und statische Typisierung bietet. Angular Anwendungen werden in TypeScript geschrieben. Hier sind einige Vorteil von TypeScript gegenĂŒber JavaScript.
- Statische Typisierung: Erkenne Fehler zur Entwicklungszeit und definiere Typen fĂŒr Variablen und Funktionen.
- ModularitĂ€t: Teile deinen Code in Module fĂŒr bessere Struktur und Wartbarkeit.
- Erweiterte Funktionen: Nutze Interfaces und Enums, um komplexe Datenstrukturen zu modellieren.
- Ăberfliege die TypeScript Dokumentation zu den wichtigsten Datentypen.
- Sieh dir die innFactory Best Practices zu TypeScript an.
HTML wird verwendet, um die Struktur und den Inhalt von Webseiten zu definieren. Als Markupsprache beschreibt es grob zusammengefasst die Eigenschaften und den Aufbau jeder Website.
- Elemente werden durch Tags definiert. Z.B. ein Button mit dem
<button></button>
-Tag. - Attribute: HTML-Elemente können Attribute enthalten. Z.B. ein
<a></a>
Link-Tag mit dem href-Attribut.<a href="https://beispiel.de/">Besuche meine Website</a>
- Semantische HTML-Elemente wie
<header></header>
,<footer></footer>
,<article></article>
und<section></section>
um Struktur des Inhalts klarer zu machen. - Weitere Ressourcen: Du kannst mehr ĂŒber HTML lernen, indem du die offizielle MDN-Webdokumentation besuchst, die detaillierte Informationen und Beispiele bietet.
Da TypeScript das Programmverhalten und HTML den Website Aufbau ĂŒbernimmt, benötigst du in der Webentwicklung noch eine weitere Technik, damit die Seiten auch wirklich schön werden. Farben, Schriftarten, AbstĂ€nde uvm. werden ĂŒber CSS definiert. Damit CSS eine noch bessere Wiederverwendbarkeit bekommt gibt es die CSS Erweiterung SCSS.
- Sieh dir an wie dieses HTML Beispiel etwas weiter unten im Artikel mit Hilfe einer CSS Datei [stilisiert wird].css-using-common-selectors
- In diesem SCSS Guide siehst du wie CSS in SCSS Form geschrieben wird.
Hier findest du noch eine Auflistung an Tipps die Besonders fĂŒr Einsteiger hilfreich sind und dich vor ewigem RĂ€tseln und Fehlersuchen bewahren sollen, wenn du mal nicht weiterkommst.
-
Hast du Alle Dateien gespeichert? Wenn du vergisst eine Datei mit
Ctrl + S
zu speichern merkst du es meist nicht direkt. Wenn du auf sonderbare Fehler triffst, ist es hilfreich das gesamte Projekt ĂŒberFile -> Save All
zu speichern. -
Manchmal wirst du beim Entwickeln Syntaxfehler bekommen, die dann live in dieser Konsole angezeigt werden. Normalerweise sollten sich die Konsole beim Speichern einer Datei automatisch verÀndern. Es kann jedoch auch helfen den Client mit
q
oderCtrl + C
zu beenden und dann neu zu starten. Das kannst du beliebig oft machen und hat keine Auswirkungen. -
In der Challenge wirst du oftmals aufgefordert Angular Komponenten / Dateien anzupassen. VS Code stellt mehrere Tools zur VerfĂŒgung, damit du diese im Projekt findest. Ăber die Suchleiste oben, kannst du nach Dateien suchen. Gib dort z.B. einmal "home-page" ein. In VS Code kannst du auĂerdem ĂŒber
Edit -> Find in Files
global nach Programmcode suchen. Suche z.B. einmal nach "console.log('Willkommen in den DevTools!');". -
Oftmals wirst du auf Komponenten oder externe Bibliotheken zugreifen. Hast du sie nicht importiert, werden sie in VS Code rot unterringelt (= Linting). Hovere mit der Maus darĂŒber. Klicke auf
Quick Fix ...
und dann auf den richtigen Importpfad der Bibliothek. Verwendest du hier den falschen Import, funktioniert die Logik ggf. nicht richtig.
Das war aber eine Menge Input. Jetzt wird programmiert! Mache mit der â ą. Challenge weiter.
Im Gegensatz zu Chuck Norris, machen wir Entwickler Fehler. Das gehört einfach zum Lernprozess dazu đ§.
- Versuche im Browser eine Seite zu öffnen die es in unserer Webapp noch nicht gibt z.B. http://localhost:4200/diese-seite-gibts-ganz-bestimmt.
- Was siehst du? Eine leere Seite nur mit Header und Footer? Wie langweilig! In unserem src/pages/ Ordner fehlt noch eine "NotFoundPage".
- In Angular erstellst du neue Komponenten am Besten aus der Kommandozeile.
- Ăffne die Konsole und fĂŒhre nun den Befehl
npx ng generate component ../pages/not-found-page
aus. Im src/pages/ Ordner sollte nun eine neue Angular Komponente "NotFoundPage" erscheinen. - Angular kommt standardmĂ€Ăig mit einer Routing Bibliothek. Diese ist in der Datei app.routes.ts konfiguriert.
- FĂŒge als neuen Pfad die neue "NotFoundPage" Komponente hinzu. Beim Pfad verwendest du
**
. Das steht beim Angular Routing fĂŒr alle nicht-angegebenen Pfade. - Teste alles erneut aus. Du solltest den Text "not-found-page works!" sehen.
"Es gibt keinen Schönheitswettbewerb mit Chuck Norris, denn alle wissen, dass er der einzige Gewinner wÀre."
- Sieh dir einmal andere Not-Found Seiten aus dem Internet an z.B.
- Passe nun die "NotFoundPage" an und gestalte Sie mit HTML und CSS aus. Hier sind deiner KreativitÀt keine Grenzen gesetzt! Lasse dir gerne mit Verwendung von Bildern, Text oder sogar CSS-Animationen etwas einfallen.
GlĂŒckwunsch! Du hast soeben dein erste Angular Komponente entwickelt. Kannst du Chuck Norris aber auch im Witze-Duell schlagenâ
In der Folgenden Challenge lernst du das Konzept der Angular Services am Beispiel des bereits bestehenden "FavouriteChuckJokesService" kennen. Im Anschluss erstellst du eine Komponente, mit der du eigene Witze eingeben kannst. Dabei kommst du auch mit der Bibliothek "Angular Material" in BerĂŒhrung. SpĂ€ter wirst du auch etwas ĂŒber den Verwendungszweck der reaktiven Angular Signals lernen.
- Sieh dir die "JokesPage" einmal an. Gibst du einen Witz ein und klickst auf den "FAVORISIEREN" Button, erscheint er in der "FavouritesPage" bzw. der "JokeTable".
- Das macht das Global State Management ĂŒber sogenannte Services in Angular möglich.
- Sieh dir den Code zur "ChuckJokesCard" Komponente, zum "FavouriteChuckJokesService" Service und die "updateChucksJokeTableData()" Methode in "JokesTable" genauer an.
- Die Methode lÀdt die im "FavouriteChuckJokesService" gespeicherten Witze jedes mal, bei Aufruf der in die Tabelle. Probiere es gerne selbst aus indem du neue Chuck Norris Witze lÀdst und favorisierst.
Damit du mit Chuck Norris in Konkurrenz treten kannst, wirst du nun auch eine Eigene-Witze Eingabefeld implementieren.
- Generiere passend zur Komponente "ChuckJokesCard" ĂŒber die Konsole eine neue "OwnJokesCard".
- FĂŒge die Komponente im HTML der "JokesPage" hinzu.
- Kannst du analog zur "ChuckJokesCard" die "GenerationCard" im HTML der "OwnJokesCard" wiederverwenden? Diese Wiederverwendung ist die Angular Content Projection. Diese Syntax ist bereits etwas komplexer und du musst sie noch nicht ganz verstehen.
- FĂŒge in die neue "OwnJokesCard" einen Input und einen Favorisieren Button auf der Witze Seite unterhalb der Chuck's Witze Komponente hinzu.
- Hilfreiche Dokus dazu findest du hier zum Input und hier zum Button.
Nun hast du ein Frontend mit Eingabefeld und Button. Die Eingabe musst du nun an die Tabelle der "JokesTable" weitergeben. Diese globale VerknĂŒpfung von Daten heiĂt auch "Global State Management" und ist in verschiedenen Frameworks unterschiedlich aufgebaut. In Angular geht dies ĂŒber Services.
- Sieh dir dazu die offizielle Dokumentation an und schlieĂe das Angular Services Tutorial ab.
- Sieh dir den "FavouriteChuckJokesService" und seine Verwendung in "ChuckJokesCard" und der "JokesTable" genauer an.
- Implementiere nun auch einen "FavouriteOwnJokesService". Das geht auch ĂŒber den
npx ng generate service ../shared/services/(name)
Befehl. - Der Service soll auch nur ĂŒber die "add()", "remove()" und "getAll()" Methoden verwendbar sein.
- FĂŒge in der "OwnJokesCard" eine neue Methode fĂŒr das favorisieren hinzu. Gebe den neuen, eigenen Witz ĂŒber die "add()" Methode an den Service.
- Passe die "JokesTable" so an, dass im Konstruktor nun auch deine Eigenen Witze mitgeladen werden. Dazu kannst du eine neue Methode "updateOwnJokesTableData()" erstellen.
Im Anschluss wirst du die "JokesTable" erweitern. Du hast versehentlich einen peinlichen Witz favorisiert? Hoffentlich sehen das nicht Toni, Maxi und Tobi! đ In der Tabelle gibt es bereits einen Löschen Button. Aber dessen Funktion ist leider noch nicht implementiert.
- Implementiere die "deleteRow()" Methode und greife auf die "remove()" Methoden deiner Services "FavouriteChuckJokesService" und "FavouriteOwnJokesService" zu.
- FĂ€llt dir auf, dass die Löschung in der Tabelle erst aktualisiert wird, wenn du auf den "AKTUALISIEREN" Button klickst, oder auf eine andere Seite z.B. "Start" und wieder zurĂŒckwechselst?
Die Tabellendaten aktualisieren sich nur manuell. Der Grund dafĂŒr ist, dass jemand dem Datenobjekt "tableData" mitteilen muss, dass sich die Witze der Services geĂ€ndert haben. Um dies eleganter zu gestalten, gibt es in Angular die Verwendung des reaktiven Programmierstils. Das geht mit sogenannten Signals.
-
Lies dir den Eintrag ĂŒber Signals in der offiziellen Angular Dokumentation durch.
-
Sieh dir den "FavouriteChuckJokesSignalService" an. Als Hilfestellung ist er im Projekt bereits implementiert. Bemerkst du die wesentlichen Unterschiede zum "FavouriteChuckJokesService"?
- Das private Datenobjekt "data", ein verÀnderbares Signal vom Typ "WriteableSignal", ist hier eine Funktion und auf dessen Inhalt wird mit "data()" zugegriffen. ZusÀtzlich gibt es das neue, öffentliche Datenobjekt "$data". Es ist ein "read-only", berechnetes (=computed) Signal ebenfalls vom Typen "Signal".
-
Importiere zunÀchst an allen Stellen statt des bisherigen "FavouriteChuckJokesService" den bisher noch nicht verwendeten "FavouriteChuckJokesSignalService".
-
Jetzt wird es interessant: Anstatt "tableData" im Konstruktor mit den Services zu aktualisieren, wird es sich in Zukunft als "computed" Signal von selbst berechnen.
-
Entferne den Programmcode fĂŒr den "constructor()" und die update Funktionen aus der "JokesTable".
-
Entferne die aktuelle "tableData" Zuweisung und erstelle sie stattdessen als computed Datenobjekt. Hier eine Vorlage dafĂŒr:
protected tableData = computed<JokeTableRow[]>(() => { const data: JokeTableRow[] = []; // Hier musst du nun data mit dem Signal $data aus dem "FavouriteChuckJokesSignalService" befĂŒllen return data; }
-
Da "tableData" nun ein Signal ist, musst du ĂŒberall dort, wo es bisher verwendet wird anstelle von "tableData" mit "tableData()" darauf zugreifen.
Wenn alles implementiert ist, aktualisieren sich die Tabellendaten nun, bei Klick auf den Löschen Button von selbst đ€Ż. Allerdings werden jetzt die eigenen Witze nicht mehr angezeigt. So gewinnst du leider keinen Wettbewerb gegen Chuck Norris.. đ€·ââïž
- Erstelle einen neuen "FavouriteOwnJokesSignalService". Die Methoden "add()", "remove()" und "getAll()" mĂŒssen angepasst werden. Orientiere dich dabei am "FavouriteChuckJokesSignalService".
- Die Methode "setFromDatabase()" kannst du bis Challenge â „ ersteinmal ignorieren.
- Tausche auch den vorherigen Service ĂŒberall durch den neuen Signal Service aus.
- ErgÀnze nun das "tableData" Signal der "JokesTable" Komponente auch mit dem "$data" Signal aus deinem neuen "FavouriteOwnJokesSignalService".
Probiere es gleich im Browser aus. Ab sofort berechnet sich das "tableData" Datenobjekt, bei jeglicher VerÀnderung des Eigenen und des Chucks Witze Signal Services von selbst neu. Die Tabelle aktualisiert sich im Frontend damit automatisch bzw. reaktiv.
Der "AKTUALISIEREN" Button wird jetzt nicht mehr benötigt. Es folgt den Best Practices als Entwickler, unbenutzten Programmcode oder veraltete Features immer direkt zu entfernen um das Projekt simpel und verstÀndlich zu halten.
- Entferne nun den "AKTUALISIEREN" Button und seine Funktion. Er wird nicht mehr benötigt. Herzlichen GlĂŒckwunsch, du hast diese Challenge geschafft! Das muss gefeiert werden đ„ł!
- Suche zum Abschluss der Challenge im Internet z.B. auf Witze.net Flachwitze nach den peinlichsten Flachwitzen und fĂŒge Sie als eigene Witze hinzu.
- NatĂŒrlich kannst du sie nun auch schnellstmöglich wieder löschen, bevor andere sie lesen.
- Wenn du es jetzt aber nicht mehr abwarten kannst Bilder von sĂŒĂen Katzen zu sehen, dann mache direkt mit der â €. Challenge weiter..
Nun wird das Projekt um eine Katzen Seite erweitert. Sie wird zufÀllig neue Katzenbilder aus dem Web laden, die du dann auch favorisieren kannst.
- Erstelle im src/pages/ Ordner eine neue Komponente "CatsPage". Nutze dafĂŒr ebenfalls die Generierung aus der Konsole.
- Erweitere die Routes Datei um einen neuen "cats" Pfad der auf die neue Komponente verweist. Du solltest sie jetzt im Browser öffnen können.
- Damit die Seite auch per Header aufrufbar ist, musst du sie in der Navigation Komponente im HTML erweitern.
- Damit ist die Seite fertig konfiguriert đ.
Die Katzenseite soll ein Bild und zwei Buttons z.B. "NEU" und "FAVORISIEREN" beinhalten, um die Katze spÀter neu zu generieren und zu favorisieren. Konzentriere dich erst einmal auf das HTML und CSS. Du kannst wie bei den Witzen die GenerationCard Komponente wiederverwenden.
- Tipp: Sieh dir fĂŒr das Image Element wieder die offizielle Dokumentation an.
- Verwende fĂŒr das Bild erst einmal das public/cat-placeholder.png.
Eine Programmierschnittstelle auch kurz API ermöglicht in der Softwareentwicklung den einfachen Zugriff auf externen Programmcode. Mit den Chuck Norris Witzen ist bereits eine online API implementiert.
- Sieh dir den JokeApiService im Projekt an. Die URL zur API befindet sich in der src/app/app.constants.ts Datei.
- Rufe die API per Link im Browser auf https://api.chucknorris.io/jokes/random. Was siehst du?
- Du siehst die JSON Antwort der API.
- Aktualisiere die Seite neu. Was verÀndert sich?
- Der HTTP Zugriff auf die API erfolgt in Angular 20 vorzugsweise mit dem HttpClient und RxJS Observables. Sieh dir die offizielle Dokumentation zu den beiden an.
- Verstehst du den Zugriff auf den Service und die reaktive Resource in der ChuckJokesCard Komponente?
- Da TypeScript empfiehlt alle Datenobjekte zu typisieren, ist im Projekt auch die JSON RĂŒckgabe typisiert. Das Modell siehst du in src/models/api-response-chuck-joke.ts.
Bei Klick auf den "NEU" Button soll in Zukunft ein zufÀlliges Katzenbild geladen werden. Dazu kannst du die Katzen API aus dem Web benutzen. Sie liefert dir jeweils eine neue Katzenbild URL, die du dann im "src" Attribut des Bildes verwendest.
- Sieh dir die JSON der Katzen API im Browser an https://cataas.com/cat?json=true.
- Du kannst auch den Inhalt des "url" keys einmal im Browser öffnen. Du siehst jeweils eine neue zufÀllige Katze.
- Erstelle nun einen "CatApiService" passend zum "JokeApiService". Greife dann auf die reaktive Resource zu. Du kannst dich wieder an der "ChuckJokesCard" orientieren.
- Typisiere die JSON RĂŒckgabe. Dazu erstellst du eine neue Datei unter src/models/ und markierst den Typen z.B. "CatData" mit "export type" als im Projekt global benutzbar.
- Implementiere eine neue "urlCatPicture()" Methode in der "CatsPage", die jeweils die URL des "CatApiService" zurĂŒckgibt.
- Orientiere dich dabei einfach an der Methode "jokeDisplayed()" der "ChuckJokesCard".
- Implementiere eine "fetchNewCat()" Methode, die die Resource neu lĂ€dt. Rufe sie ĂŒber den "NEU" Button auf.
- Verwende anstelle des "cat-placeholder.png" Bildes nun die zufÀllige URL.
- Auf das "src" Attribut des Image greifst du von nun an mit eckigen Klammern zu. So markierst du in Angular HTML dynamische, sich verÀndernde Attribute.
<img [src]="urlCatPicture" />
Super, du hast soeben erfolgreich eine API angebunden. Bei Klick auf den "NEU" Button sollte jeweils ein neues Katzenbild erscheinen. Wie niedlich!
Du hast es vielleicht schon erraten đ.. Im Anschluss wirst du analog zur Witzetabelle eine neue Katzentabelle erstellen. Dort erscheinen dann die favorisierten Katzen.
- Erstelle eine neue "CatsTable" Komponente. Kopiere einige Teile der "JokesTable". Der Syntax hierfĂŒr ist komplex, du kannst die sie auch in der Angular Material Dokumentation nachschlagen.
- Binde die "CatsTable" Komponente auch in die "FavouritesPage" ein. Sie wird nun auch auf der Seite sichtbar.
- Aus der Signal Challenge kennst du bereits den "FavouriteChuckJokesSignalService". Erstelle einen neuen "FavouriteCatsSignalService".
- Er speichert anstelle von "JokeData" Daten vom Typen "CatData".
- Nun musst du auch in der "CatsTable" Komponente die Tabellendaten als "computed" berechnen, damit sich die favorisierten oder gelöschten Katzen URLs reaktiv aktualisieren.
Die Angular Chuck Norris Webapp verfĂŒgt bereits ĂŒber weitreichende Features! Du hast bereits eine weitere online API angebunden, auf der Startseite wird ĂŒber Chuck Norris selbst erfundenen KampfkĂŒnste berichtet đ. Es gibt die Möglichkeit Witze und Katzen Favoriten hinzuzufĂŒgen und zu löschen. Sogar eigene Witze können mit denen von Chuck Norris in Konkurrenz treten. Durch die reaktive Programmierung werden die Ănderungen unmittelbar in den Tabellen aktualisiert. Mit der Verwendung von Services auf die von ĂŒberall aus zugegriffen werden kann, folgst du den Best Practices der Modularisierung!
Einen Nachteil hat unsere App bisher noch. Klickst du den Refresh Button im Browser, gehen alle favorisierten Witze und Katzen fĂŒr den Benutzer verloren. Wie schön wĂ€re es, wenn du ĂŒber Wochen und Monate die Besten Witze speichern und die Liste damit erweitern könntest đ€©.
Eine solche zuverlĂ€ssige Option, um Daten zu speichern und darauf jederzeit und von ĂŒberall aus zugreifen zu können, ist die Verwendung einer "Cloud Datenbank". Im Folgenden wirst in einem bereits im Projekt integrierten Cloud Service anmelden. SpĂ€ter wirst du das Projekt mit einer selbsterstellten, kostenlosen Google Firebase Datenbank verknĂŒpfen.
Im Projekt ist bereits eine externe Datenbank in Google Firebase mit Firestore und dem Account der innFactory GmbH verknĂŒpft.
- Sieh dir die Konfiguration einmal an.
- Unter package.json sind die "@angular/fire" und "@firebase" Bibliotheken als AbhÀngigkeiten angegeben.
- Unter src/app/app.config.ts sind Firebase und Firestore Services anwendungsweit zur VerfĂŒgung gestellt.
- Unter src/environments/environment.development.ts sind die Anmeldedaten fĂŒr den innFactory Firebase Account hinterlegt.
- Im "JokeDatabaseService" erfolgt schlussendlich der Zugriff auf die Datenbank.
- Erstelle dir in der OberflÀche der App einen neuen Benutzer und melde dich damit an.
- Klicke auf den Benutzer Icon im Header der Webapp und dann auf Registrieren.
- Verwende am Besten deine innFactory E-Mail. Im Hintergrund wird ein neuer Benutzer im innFactory Firebase angelegt.
Als nÀchstes werden wir die Chuck Norris Witze beim favorisieren nicht nur wie bisher an den Service, sondern auch an die Datenbank weitergeben.
- HĂ€nge die "add()" und "remove()" Methodenaufrufe des "JokeDatabaseService" einfach denjenigen des "FavouriteChuckJokesSignalService" am Ende an. Den Witz bzw. die ID in den Methoden musst du natĂŒrlich weitergeben.
- Melde dich erneut ĂŒber das Benutzer Icon an.
- Wenn du nun Chuck Norris Witze favorisierst, werden sie nun automatisch der Datenbank hinzugefĂŒgt.
- Melde dich nun ab und lade die Seite im Browser neu, sodass die Favoriten verschwinden. Melde dich nun erneut an. Die Witze sollten wieder erscheinen.
Nicht schlecht! Du hast die bestehende externe Datenbank erfolgreich angebunden đšâđ».
Damit nun auch deine eigenen Witze verewigt werden, kannst du ebenfalls den "JokeDatabaseService" in deinem "FavouriteOwnJokesSignalService" verwenden. Allerdings mĂŒssen beide noch ein wenig angepasst werden.
- HĂ€nge die "add()" und "remove()" des Datenbank Service an diejenigen des Services fĂŒr eigene Witze.
- Aktuell wird immer "CREATOR_CHUCK" als Ersteller verwendet. Erweitere die "JokeDatabaseService" "add()" Methode um einen Parameter fĂŒr den Ersteller "creator" und benutze diesen statt dem Festtext.
- Jetzt kannst du den Ersteller auch jeweils passend im "FavouriteOwnJokesSignalService" und "FavouriteChuckJokesSignalService" weiterreichen.
- Fast geschafft. Aktuell werden im Projekt bei Anmeldung die Witze geladen und bei Abmeldung wieder entfernt. Das musst du nun fĂŒr die eigenen Witze auch ergĂ€nzen.
- Kopiere die Methode "setFromDatabase()" aus dem "FavouriteChuckJokesSignalService" in den eigenen. Tausche die Konstante "PREFIX_ID_CHUCK_JOKES" jeweils durch "PREFIX_ID_OWN_JOKES" aus.
- Passe die Methode "loadJokesFromDatabase()" der "Login" Komponente src/security/login/ an.
- Neben der "chuckJokeTableData: JokeData[]" Konstante fĂŒgst du am Besten auch eine "ownJokeTableData: JokeData[]" hinzu.
- Diese BefĂŒllst du dann beim Ersteller "CREATOR_OWN".
- Im Anschluss fĂŒgst in "Login" den Zugriff auf deinen Service "FavouriteOwnJokesSignalService" mit
inject()
hinzu. - Nun musst du noch dessen "setFromDatabase()" ansprechen und die "ownJokeTableData" ĂŒbergeben.
- Erweitere die "logout()" Methode der Menu Komponente und setze bei erfolgreichem Abmelden die Witze des FavouriteOwnJokesSignalService mit
setFromDatabase([])
auf einen leeren Datensatz.
Fertig! Nun werden auch deine eigenen Witze in der Datenbank gespeichert. Teste es gleich einmal aus. Melde dich wieder ab und lade die Seite im Browser neu, sodass die Favoriten verschwinden. Melde dich nun erneut an. Deine eigenen Witze sollten nun auch wieder erscheinen. Auch das Löschen sollte funktionieren.
Bisher bist du vor allem mit der Frontend Entwicklung in BerĂŒhrung gekommen. Im Folgenden wirst du einen eigenen Google Firebase Account Projekt erstellen und an die Angular Chuck Norris Webapp daran anbinden.
- Melde dich auf der Google Firebase Console mit einem bestehenden Google Konto an, oder erstelle ein neues Google Konto mit deiner innFactory E-Mail.
- Klicke auf "Neues Firebase-Projekt erstellen" und gib z.B. "angular-chuck-norris" als Projektnamen ein. Du musst weder Gemini noch das Entwicklerprogramm oder Google Analytics aktivieren.
- Navigiere nach
ProjektĂŒbersicht -> Projekteinstellungen -> Allgemein
. UnterMeine Apps
klickst du auf das</>
Symbol fĂŒr Web um Firebase zu einer Webapp hinzuzufĂŒgen. - Benutze als Alias auch den Projektnamen "angular-chuck-norris" und klicke auf App registrieren.
- Du erhĂ€ltst eine Ăbersicht zum Setup. Das wurde aber schon fertig eingestellt. Kopiere dir nur den Inhalt mit folgendem Schema heraus:
apiKey: '...', authDomain: 'angular-chuck-norris.firebaseapp.com', projectId: 'angular-chuck-norris', storageBucket: 'angular-chuck-norris.firebasestorage.app', messagingSenderId: '...', appId: '...',
- FĂŒge diesen Inhalt nun in die src/environments/environment.development.ts Datei in das "firebase" Attribut ein.
- Stoppe den laufenden Angular Client im Terminal mit
Cmd + C
oder durch Eingabe vonq + Enter
fĂŒr "quit". - Starte den Client neu mit
npm start
- In der Browser Konsole sollten keine Fehler wie z.B. "auth/invalid-api-key" erscheinen.
Nun ist die App erfolgreich mit Firebase verbunden. Beim Registrieren oder Anmelden erhĂ€ltst du noch richtigerweise einen "â ... fehlgeschlagen" Hinweis.
Die Authentifizierung per E-Mail und Passwort muss im Firebase Projekt aktiviert werden.
-
Navigiere im Firebase HauptmenĂŒ im Reiter links nach
Entwickeln -> Authentication
und klicke auf denLos geht's
Button. -
Bei Anmeldemethode aktivierst du E-Mail-Adresse/Passwort.
E-Mail-Link
kannst du deaktiviert lassen. BestÀtige die Konfiguration mitSpeichern
. -
Jetzt sollte die Registrierung und Anmeldung unmittelbar funktionieren. Unter
Authentication -> Nutzer
kannst du den neu erstellten Benutzer sehen. -
Damit nun auch die Datenbank-Speicherung funktioniert, musst du in Firebase noch Firestore Datenbanken aktivieren.
-
Navigiere im Firebase HauptmenĂŒ im Reiter links nach
Entwickeln -> Firestore Database
und klicke auf denDatenbank erstellen
Button. WĂ€hle einen Standort in Europa. -
WĂ€hle die Option
Im Produktionsmodus starten
und bestÀtige mit demErstellen
Button. -
Navigiere nun im Reiter oben auf Regeln. Du siehst bereits voreingestellte Zugriffsregeln die du nun entfernst. Folgende Regeln kannst du komplett kopieren und einfĂŒgen. Du musst nichts weiter anpassen.
rules_version = '1'; service cloud.firestore { match /databases/{database}/documents { // Only read, create for signed in users match /users/{userID} { allow delete: if false; allow read, create: if isSignedIn() && isAllowedToChangeTable(userID); // Only read, create, delete in table with userID equals email match /jokes/{jokeID} { allow delete, create, read, update: if isSignedIn() && isAllowedToChangeTable(userID); } // Only read, create, delete in table with userID equals email match /cats/{catID} { allow delete, create, read, update: if isSignedIn() && isAllowedToChangeTable(userID); } } } function isSignedIn() { return request.auth != null; } function isAllowedToChangeTable(userID) { return request.auth.token.email == userID; } }
-
Klicke auf den
Veröffentlichen
Button
Fertig! Du hast deine eigene Datenbank mit Benutzer Authentifizierung richtig erstellt und konfiguriert đ„ł. Teste es direkt einmal aus. Nun solltest du eigene Witze und Chuck Norris Witze ganz einfach favorisieren können, dich ab- und anmelden und sie erscheinen erneut.
In der letzten Challenge wirst du einen neuen Service erstellen, der fĂŒr die Verwaltung einer Katzen-Datenbanktabelle verantwortlich ist. Dieser Service wird bei der Benutzeranmeldung geladen und beim Logout gelöscht. Hier sind die Details zu den erforderlichen Schritten.
- Erstelle unter src/models/ einen neuen Typen "FirebaseCatTableRow". Er bekommt die Attribute "id" und "url" jeweils vom Typ "string".
- Erstelle einen neuen "CatDatabaseService". Du kannst den Code des "JokeDatabaseServices" hierfĂŒr einfach kopieren.
- Als "FIREBASE_TABLE_NAME" verwendest du die "cats" Tabelle, anstatt der jokeID jeweils eine catID.
- In der "add()" Methode benötigst du nur noch die Parameter "catID" und "url" vom Typ string. "catData" hat nur das Feld "url", das du ĂŒbergibst.
- Verwende "FirebaseCatTableRow" im "CatDatabaseService" anstelle von "FirebaseJokeTableRow". Tausche auch die ĂŒbrigen Parameternamen so aus, sodass sie zum "CatDatabaseService" passen.
- Passe auch die BefĂŒllung des "cats" Arrays in der "getAll()" Methode an.
- ErgĂ€nze nun die "add()" und "remove()" Methoden des "FavouriteCatsService" um den Aufruf des neuen "CatDatabaseService". FĂŒge eine Methode "setFromDatabase()" hinzu und verwende hier "PREFIX_ID_CATS".
- Damit die Katzen-URLs nach der Anmeldung geladen werden, fĂŒgst du der "login()" Methode der Login Komponente eine neue Methode "loadCatsFromDatabase()" hinzu. Die du bei erfolgreicher Anmeldung aufrufst.
- Bei Abmeldung soll die Katzentabelle gelöscht werden. Setze die Daten des "FavouriteCatsSignalService" in der "logout()" Methode der Menu Komponente auf ein leeres Array.
GlĂŒckwunsch, du hast alle Challenges gemeistert. Chuck Norris und die innFactory sind stolz auf deine Webdevelopment KĂŒnste đ€©.
Foto von Craig Michaud, lizenziert unter CC BY 3.0.
Angular Icon in Favicon und Readme Intro von Angular, lizenziert unter CC BY 4.0. Das Icon wurde editiert.
Dieser Abschnitt enthÀlt alle externen Links. So können sie schnell & an einer Stelle geupdated werden.
(Links unsichtbar in der Vorschau)