Zum Inhalt

Termin 4: Interaktive Webseiten, Fetch API, DOM & CSR

In dieser Einheit geht es um die clientseitige Implementierung der Interaktion zwischen Benutzer und Anwendung. Hierfür setzen wir JavaScript ein und modifizieren damit die angezeigte Webseite mit Hilfe des DOM (=Document Object Model). Ferner steht in dieser Einheit auch die asynchrone Kommunikation zwischen Server und Client mittels Fetch API und JSON im Vordergrund, so dass Statusänderungen auf der Kundenseite ohne Neuladen der Seite sichtbar werden.

Vorbereitung

Erledigen Sie diese Aufgaben VOR dem Übungstermin

Voraussetzungen:

  1. Ihre vier Seiten sind weitgehend vollständig und voll funktional.
  2. Zusätzlich haben Sie ein API-Endpunkt implementiert, der serverseitig die Daten für die Kundenseite liefert.
  3. Sie sind mit JavaScript und DOM vertraut.

Aufgaben

Clientseitige Interaktion durch JavaScript

  1. JavaScript einbinden

    • Binden Sie eine JavaScript-Datei für Ihre Webseiten im <head> ein und achten Sie drauf, dass diese nur dort verwendet wird wo Sie gebraucht wird.
      <script src="assets/js/script.js" defer></script>
      
  2. Implementieren Sie anschließend folgenden Funktionen auf der Bestellseite:

    • Ein Klick auf ein Pizzabild trägt diese Pizza in den Warenkorb ein.
    • Der Preis der Pizzen im Warenkorb wird berechnet und angepasst, wenn sich der Warenkorb ändert (durch Einfügen oder Löschen).
    • Realisieren Sie die zu erwartende Funktionalität beider Buttons die für das Löschen der Warenkorbeinträge zuständig sind.
    • Die Bestellung wird nur abgeschickt, wenn eine Lieferadresse angegeben ist und sich mindestens ein Element im Warenkorb befindet.
    • Der Bestellknopf ist deaktiviert und hat eine andere Farbe, wenn die Adresse fehlt oder keine Pizza im Warenkorb ist.
    • Beim <select> im Warenkorb werden aktuell nur die manuell ausgewählten Elemente übertragen. Überlegen Sie sich eine Lösung, wie sich dieser Vorgang automatisieren lässt und stattdessen immer alle <option>Elemente vor dem Abschicken ausgewählt werden.
  3. Abschicken von Formularen ohne Submit-Button

    • Auf der Bäcker- und Fahrerseite wird eventuell noch ein Submit-Button verwendet, um die Formulare abzuschicken.
    • Ändern Sie die Formulare so ab, dass sie abgeschickt werden, wenn ein Radiobutton angeklickt wird.
    • Dazu geben Sie dem Formular, das die Radiobuttons umschließt, eine ID und verwenden diese ID beim Inline-Eventhandler onclick von den Radiobuttons um das Formular beim Anklicken abzuschicken:
      <input type="radio" onclick="document.forms['formid'].submit();" />
      
    • Alternativ: Fügen Sie in Ihrer JavaScript-Datei einen Event Listener hinzu. Sobald ein Radiobutton mit z.B. der CSS-Klasse auto-submit angeklickt wird, soll das umschließende Formular automatisch abgeschickt werden.
      const form = document.getElementById("formid");
      const radios = form.querySelectorAll(".auto-submit");
      
      radios.forEach(radio => {
          radio.addEventListener("click", () => {
              form.submit();
          });
      });
      

Aktualisierung der Kundenseite mittels Fetch API und JSON

Die Kundenseite soll den Status der Pizzen in Echtzeit aktualisieren, ohne die Seite neu zu laden. Dafür werden nur die Bestelldaten per fetch im JSON-Format vom Server abgerufen und mit JavaScript in das DOM geschrieben. Änderungen auf der Bäcker- oder Fahrer-Seite sollen unmittelbar auf der Kundenseite sichtbar sein.

Den API-Endpunkt /statusApi, welcher die Daten liefert, haben Sie bereits in der letzten Übung implementiert. (siehe Termin 3: Sessionmanagement, Sicherheit, API-Endpunkte & Fachgespräch)

Gehen Sie wie folgt vor:

  1. Einbinden der JavaScript-Datei

    • Binden Sie die separate JavaScript-Datei im <head> der Kundenseite ein:
      <script src="assets/js/customer.js" defer></script>
      
    • Diese Datei soll natürlich nur auf der Kundenseite erscheinen. Überlegen Sie sich wie Sie das am Besten realisieren.
  2. Implementieren Sie die Logik zum Datenaustausch mit der Fetch API

    • Nachdem nun serverseitig der API-Endpunkt zum Liefern der Daten vorliegt, müssen Sie diesen nurnoch anfragen und die angefragten Daten verarbeiten.

    • Schreiben Sie die Funktion requestData(), die die Daten mit fetch() vom Server abruft:

      async function requestData() {
          try {
              const response = await fetch("statusApi");
      
              if (!response.ok) {
                  throw new Error(`Fehler: ${response.status}`);
              }
      
              const data = await response.json();
              process(data);
          } catch (error) {
              console.error("Übertragung fehlgeschlagen:", error);
          }
      }
      

    • Implementieren Sie zusätzlich die Methode process(), welche die erfolgreiche Antwort verarbeitet und entweder nur den Status oder den gesamten Bestellcontainer aktualisiert (Siehe Punkt 4).
      function process(data) {
          // Hier sollen die empfangenen Daten verarbeitet werden
      }
      
  3. Führen Sie die Aktualisierung mit fetch alle 2 Sekunden durch

    • Die Anfrage nach den aktuellen Daten einer Bestellung erfolgt mittels zyklisch ausgeführten Aufrufen (= Polling) durch die setInterval() Funktion.
    • Das Polling soll erst starten, nachdem die Seite komplett vom Browser geladen und geparst wurde.
      document.addEventListener("DOMContentLoaded", () => {
          requestData();                   // einmal sofort
          setInterval(requestData, 2000); // dann alle 2 Sekunden
      });
      
  4. Optional: Client-Side-Rendering der gesamten Bestellung statt nur des Status

    • Der Bestellbereich der Kundenseite kann auch vollständig clientseitig gerendert werden.
    • Der entsprechende Bereich enthält nur ein leeres Container-Element samt ID und wir nicht mehr serverseitig gerendert.
      <div id="order">...</div>
      
    • Sämtliche Bestelldaten (Pizzen, Anzahl, Status usw.) werden über den API-Endpunkt /statusApi als JSON geladen. Anschließend erzeugt die Funktion process() aus den empfangenen Daten die benötigten HTML-Elemente und fügt diese in den leeren Container ein.
    • Bei jeder Polling-Aktualisierung wird, um es einfach zu halten, der komplette Inhalt vom Container neu aufgebaut.
    • Das restliche Seitenlayout (Header, Navigation, Footer usw.) werden weiterhin serverseitig gerendert.
    • Dadurch werden alle Änderungen an der Bestellung (nicht nur der Status) ohne Neuladen der Seite sofort sichtbar und neue Bestellungen erscheinen automatisch, sobald sie existieren.

Bei Problemen mit DOM oder JavaScript

  • Im Reiter Konsole finden Sie Hinweise auf Fehler im Code, die der Browser nicht anzeigt. Wenn Ihr Code nicht funktioniert, steht hier wahrscheinlich der Grund dafür.
  • Im Browserfenster können Sie im Rechte-Maus-Menü Element untersuchen/Inspect auswählen und sehen den zugehörigen Quellcode zum ausgewählten Element.
  • Wichtig: Falls sich Ihr Code nicht aktualisiert, leeren Sie den Browser-Cache, deaktivieren Sie das Caching im Network-Tab der Developer Tools oder hängen Sie beim Einbinden von JavaScript- oder CSS-Dateien nach Änderungen einen Query-Parameter (z. B. ?v=1.0, ?v=1.1 usw.) an.
    <script src="assets/js/script.js?v=1.0"></script>
    

Meilenstein

Stand jetzt sind die clientseitigen Interaktionen sowie die zyklische Datenaktualisierung über Fetch API und JSON umgesetzt. Damit arbeitet Ihre Anwendung bereits interaktiv und reagiert ohne vollständiges Neuladen der Seite.

Nachbereitung

Setzen Sie noch eventuell fehlende Teile der obigen Aufgabe bis zum Abgabetermin um. Entwickeln Sie spätestens bis zum nächsten Praktikumstermin auch das responsive Design für Ihren Webservice (siehe Selbststudium II: Styling & Responsives Design).

Ergebnisse

Die folgenden Ergebnisse müssen für eine erfolgreiche Durchführung der Praktikumseinheit vorliegen:

Ergebnisse

  • Vollständige Implementierung der Bestellseite mit Berechnung, Löschung und Prüfungen durch valides JavaScript und DOM
  • Die Formulare auf der Fahrer und Bächerseite werden jetzt mit JavaScript abgeschickt
  • Vollständige Implementierung der zyklischen Aktualisierung der Kundenseite über fetch() und JSON