content

Edit Button

Add a Delete Button in the table.

app.js:

let editingId = null;

async function fetchStudents() {
  const statusEl = document.getElementById("status");
  const tbody = document.querySelector("#students-table tbody");

  try {
    statusEl.textContent = "Load data...";
    const res = await fetch("/students");
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
    const students = await res.json();

    tbody.innerHTML = "";
    for (const s of students) {
      const tr = document.createElement("tr");

      const tdId = document.createElement("td");
      tdId.textContent = s.id;

      const tdName = document.createElement("td");
      const tdCourse = document.createElement("td");
      const tdActions = document.createElement("td");

      if (editingId === s.id) {
        // Edit mode
        const nameInput = document.createElement("input");
        nameInput.type = "text";
        nameInput.value = s.name;
        nameInput.className = "input-sm";

        const courseInput = document.createElement("input");
        courseInput.type = "text";
        courseInput.value = s.course;
        courseInput.className = "input-sm";

        tdName.appendChild(nameInput);
        tdCourse.appendChild(courseInput);

        const saveBtn = document.createElement("button");
        saveBtn.textContent = "Speichern";
        saveBtn.className = "save-btn";
        saveBtn.onclick = async () => {
          if (!nameInput.value.trim() || !courseInput.value.trim()) {
            document.getElementById("status").textContent = "Name und Kurs erforderlich.";
            return;
          }
          await updateStudent(s.id, {
            name: nameInput.value.trim(),
            course: courseInput.value.trim(),
          });
          editingId = null;
          await fetchStudents();
        };

        const cancelBtn = document.createElement("button");
        cancelBtn.textContent = "Abbrechen";
        cancelBtn.className = "cancel-btn";
        cancelBtn.onclick = async () => {
          editingId = null;
          await fetchStudents();
        };

        tdActions.append(saveBtn, " ", cancelBtn);
      } else {
        // View mode
        tdName.textContent = s.name;
        tdCourse.textContent = s.course;

        const editBtn = document.createElement("button");
        editBtn.textContent = "Bearbeiten";
        editBtn.className = "edit-btn";
        editBtn.onclick = () => {
          editingId = s.id;
          fetchStudents();
        };

        const delBtn = document.createElement("button");
        delBtn.textContent = "Löschen";
        delBtn.className = "delete-btn";
        delBtn.onclick = async () => {
          if (!confirm(`Student ${s.name} wirklich löschen?`)) return;
          await deleteStudent(s.id);
          await fetchStudents();
        };

        tdActions.append(editBtn, " ", delBtn);
      }

      tr.append(tdId, tdName, tdCourse, tdActions);
      tbody.appendChild(tr);
    }

    statusEl.textContent = `Geladen: ${students.length} Studenten`;
  } catch (err) {
    console.error(err);
    statusEl.textContent = "Fehler beim Laden der Daten.";
  }
}

let editingId = null;

Is a simple state variable — it’s used in your JavaScript frontend to remember which student row is currently being edited. null = none.

if (editingId === s.id) {
  // show inputs (edit mode)
} else {
  // show text + edit/delete buttons (normal view)
}

const tdName = document.createElement("td"); const tdCourse = document.createElement("td");

The content of the table data is empty.

It will be filled:

  • name + course

  • input field name + input field course

const nameInput = document.createElement("input"); nameInput.type = "text"; nameInput.value = s.name; nameInput.className = "input-sm"; tdName.appendChild(nameInput);

Creates an input field and adds it to the table

saveBtn.onclick = async () => {

  • async marks the function as asynchronous,
    which means it will return a Promise and allows you to use the await keyword inside it.

  • await pauses execution until the asynchronous operation (like a fetch() call) finishes.

async () => { await something(); }

Add the functionality:

app.js:

async function updateStudent(id, data) {
  const statusEl = document.getElementById("status");
  try {
    const res = await fetch(`/students/${id}`, {
      method: "PATCH",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(data),
    });
    if (!res.ok) {
      const msg = await res.json().catch(() => ({}));
      throw new Error(msg.error || `HTTP ${res.status}`);
    }
    statusEl.textContent = `Student ${id} aktualisiert.`;
  } catch (err) {
    console.error(err);
    statusEl.textContent = `Fehler beim Aktualisieren: ${err.message}`;
  }
}

JSON.stringify(data)

JSON.stringify() converts a JavaScript object (like { name: "Anna", course: "Math" }) into a JSON-formatted string (text), like this:

"{\"name\":\"Anna\",\"course\":\"Math\"}"

GIT

Do not forget.

Azur

Deploy.