\documentclass{uebung}

\author{Linus Nagel}
\chapter{7}

\begin{document}

\maketitle

\begin{exercises}
    \item Erläutern Sie, wie das Routing von Angular grundsätzlich funktioniert.

    \begin{itemize}
        \item Durch Routing werden an einer definierten Stelle der Webseite (dem router-outlet), die Templates von ausgewählten Komponenten dargestellt.
        \item Die Auswahl der anzuzeigenden Komponente erfolgt dabei abhängig von der eingegebenen URL.
    \end{itemize}

    Routen werden (z.B. mit modulebasierten Komponenten) in app-routing.module.ts definiert:
    \begin{minted}[breaklines]{ts}
    import { NgModule } from '@angular/core';
    import { Routes, RouterModule } from '@angular/router';
    const routes: Routes = [
        {path: '', component: component1}, // Root-URL
        {path: 'URL1', component: component1},
        {path: 'URL2', component: component2}
    ];
    @NgModule({
        imports: [RouterModule.forRoot(routes)],
        exports: [RouterModule]
    })
    export class AppRoutingModule { }
    \end{minted}

    Mit RouterOutlet kann wird dann gesagt, wo die Komponenten der Routen ausgegeben werden:
    \begin{minted}[breaklines]{ng2}
    <router-outlet></router-outlet>
    \end{minted}

    Anstatt normalen anchor Elementen müssen dann auch RouterLinks verwendet werden, damit kein echter redirekt passiert, sondern Angular nur die Komponenten nachläd:
    \begin{minted}[breaklines]{ng2}
    <a routerLink="/Pfad">...</a>
    \end{minted}

    \item Wie kann eine Route mit einem Parameter erstellt und ausgelesen werden?

    Routen mit Parametern werden wie folgt deklariert:
    \begin{minted}[breaklines]{ts}
    {path: 'URL/:NameDesParameters', component: Komponentenbezeichner}
    \end{minted}

    Geschrieben werden die Parameter in den RouterLinks so:
    \begin{minted}[breaklines]{ng2}
    <a routerLink="/URL/ParameterWert">...</a>
    <a [routerLink]="['/URL', ParameterWert]">...</a>
    \end{minted}

    Ausgelesen werden die Parameter in den Komponenten zu denen die Route führt (mit Dependency Injection):
    \begin{minted}[breaklines]{ts}
    constructor(private routeObject: ActivatedRoute) {
        const parameter = this.routeObject.snapshot.params['NameDesParameters'];
    }
    \end{minted}

    \item Erklären Sie, wie die Werte eines Observables empfangen werden können.

    Man übergibt der subscribe Methode eine Funktion, die aufgerufen wird, wenn Daten empfagen werden:
    \begin{minted}[breaklines]{ts}
    const data: Observable<string> = this.sendeDaten();
    const subscription = data.subscribe(value => console.log(value));
    \end{minted}

    \item Wie kann der Empfang von Observables beendet werden?

    Mit der unsubscribe Methode:
    \begin{minted}[breaklines]{ts}
    const subscription = ...;
    subscription.unsubscribe();
    \end{minted}

    \item Beschreiben Sie den Ablauf beim Speichern eines Objekts auf einem Server mittels des HttpModule.

    \begin{enumerate}
        \item In der Komponente den HttpClient per Dependency Injection erhalten
        \item auf dem httpClient object die \texttt{post} Methode aufrufen
        \item Optional noch auf dem Observable, das man von der post Methode erhält subscriben, und die Response verarbeiten.
    \end{enumerate}

    \item Erstellen Sie eine Klasse Student mit den Attributen name (string) und matrikelnummer (number). Erstellen Sie zudem mittels Template Driven Forms ein Formular sowie die zugehörige Komponentenklasse, so dass alle Daten vom Typ Student eingegeben werden können. Die Formularfelder sollen dabei mit einem Objekt vom Typ Student in der Komponentenklasse bidirektional verknüpft sein. Unter dem Formular soll sich ein Knopf befinden, der, sobald er geklickt wird, eine Methode aufruft, die den (ggf. geänderten) Inhalt des Studentenobjekts in der Konsole ausgibt.

    Student.ts:
    \begin{minted}[breaklines]{ts}
    export class Student {
      constructor(
        private _name?: string,
        private _matrikelnummer?: number,
      ) {
      }

      get name(): string|undefined { return this._name; }
      set name(name: string) { this._name = name; }

      get matrikelnummer(): number|undefined { return this._matrikelnummer; }
      set matrikelnummer(matrikelnummer: number) { this._matrikelnummer = matrikelnummer; }
    }
    \end{minted}

    student-form.ts
    \begin{minted}[breaklines]{ts}
    import { Component } from '@angular/core';
    import { FormsModule } from '@angular/forms';
    import { Student } from '../Student';

    @Component({
      selector: 'app-student-form',
      imports: [ FormsModule],
      templateUrl: './student-form.html',
      styleUrl: './student-form.css',
    })
    export class StudentForm {
      model: Student = new Student();

      print() {
        console.log(this.model)
      }
    }
    \end{minted}

    student-form.css
    \begin{minted}[breaklines]{css}
    form {
      display: flex;
      flex-direction: column;
      width: 200px;
    }
    \end{minted}

    student-form.html
    \begin{minted}[breaklines]{ng2}
    <p>Student: </p>
    <form #formularName="ngForm">
      <label for="name">Name: </label>
      <input type="text" name="name" [(ngModel)]="model.name"/>
      <label for="matrikelnummer">Matrikelnummer: </label>
      <input type="number" name="matrikelnummer" [(ngModel)]="model.matrikelnummer"/>
      <button type="submit" (click)="print()">Ausgeben</button>
    </form>
    \end{minted}

    \item Erstellen Sie das gleiche Formular wie in der vorhergehenden Aufgabe, diesmal jedoch mit Reactive Forms.  Fügen Sie dem Formular eine Validierung hinzu, die die Matrikelnummer zum Pflichtfeld macht und die prüft, ob als Matrikelnummer ausschließlich Ziffern verwendet wurden. Falls dies nicht der Fall ist, soll das Textfeld einen hellroten Hintergrund erhalten.

    student-form-reactive.ts
    \begin{minted}[breaklines]{ts}
    import { Component } from '@angular/core';
    import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
    import { Student } from '../Student';

    @Component({
      selector: 'app-student-form-reactive',
      imports: [ReactiveFormsModule],
      templateUrl: './student-form-reactive.html',
      styleUrl: './student-form-reactive.css',
    })
    export class StudentFormReactive {
      form: FormGroup = null!;

      ngOnInit() {
        this.form = new FormGroup({
          name: new FormControl<string|null>(null),
          matrikelnummer: new FormControl<number|null>(null, [Validators.required, Validators.pattern('\\d+')])
        });
      }

      print() {
        const value = this.form.value;
        const model = new Student(value.name, value.matrikelnummer);
        console.log(model);
      }
    }
    \end{minted}

    student-form-reactive.css
    \begin{minted}[breaklines]{css}
    form {
      display: flex;
      flex-direction: column;
      width: 200px;
    }

    input.ng-invalid {
      background-color: tomato;
    }
    \end{minted}

    student-form-reactive.html
    \begin{minted}[breaklines]{ng2}
    <p>Student: </p>
    <form [formGroup]="form">
      <label for="name">Name: </label>
      <input type="text" id="name" formControlName="name"/>
      <label for="matrikelnummer">Matrikelnummer: </label>
      <input type="number" id="matrikelnummer" formControlName="matrikelnummer"/>
      <button type="submit" (click)="print()">Ausgeben</button>
    </form>
    \end{minted}

\end{exercises}

\end{document}
