Wat ga je maken?
Je hebt CREATE (POST) en READ (GET). Tijd voor de laatste twee CRUD operaties:
- UPDATE - Bestaande workout aanpassen (bijv. reps van 10 naar 15)
- DELETE - Workout verwijderen uit database
HTTP Methodes voor UPDATE
Twee methodes om data aan te passen:
PUT - Vervang hele object (moet ALLE velden meesturen)
PATCH - Pas alleen bepaalde velden aan (stuur alleen wat je wilt veranderen)
Wij gebruiken PATCH omdat dat makkelijker is: je hoeft niet hele object te sturen, alleen velden die je wilt aanpassen.
PATCH - Workout Aanpassen (UPDATE)
Functie die bestaande workout kan aanpassen.
Wat moet functie doen?
- Check of ID geldig is (anders crasht app)
- Zoek workout in database
- Bestaat niet? Stuur 404 error
- Bestaat wel? Pas aan met nieuwe data
- Stuur aangepaste workout terug
Controller functie
Voeg toe aan src/controllers/workoutController.js:
// PATCH workout (aanpassen)
export const updateWorkout = async (req, res) => {
const { id } = req.params;
// Check of ID geldig is
if (!mongoose.isValidObjectId(id)) {
return res.status(400).json({ error: 'Ongeldige workout ID' });
}
try {
const workout = await Workout.findByIdAndUpdate(
id,
{ ...req.body },
{ new: true }
);
if (!workout) {
return res.status(404).json({ error: 'Workout niet gevonden' });
}
res.status(200).json(workout);
} catch (error) {
res.status(400).json({ error: error.message });
}
};
const { id } = req.params- Haal ID uit URLisValidObjectId(id)- Check ID formaatfindByIdAndUpdate()- Zoek en pas aan{ ...req.body }- Neem alle velden uit body (spread operator){ new: true }- Geef NIEUWE versie terug (niet oude)if (!workout)- Niet gevonden? Stuur 404
Wat is { ...req.body }?
Dit is de spread operator. Pakt alle velden uit req.body en zet in object.
Voorbeeld:
Als body is:
{
"reps": 15,
"load": 60
}
Wordt { ...req.body } dit:
{ reps: 15, load: 60 }
MongoDB past dan alleen deze twee velden aan. title blijft onveranderd!
Wat is { new: true }?
Standaard geeft findByIdAndUpdate() de oude versie terug (van vóór aanpassing). Met { new: true } krijg je nieuwe versie (ná aanpassing).
Voorbeeld zonder { new: true }:
Je past reps aan van 10 → 15
Response geeft: "reps": 10 (oude waarde!)
Met { new: true }:
Response geeft: "reps": 15 (nieuwe waarde!)
DELETE - Workout Verwijderen
Functie die workout uit database verwijdert.
Wat moet functie doen?
- Check of ID geldig is
- Zoek en verwijder workout in één stap
- Bestaat niet? Stuur 404 error
- Succesvol verwijderd? Stuur verwijderde workout terug (zodat je ziet wat weg is)
Controller functie
Voeg toe aan src/controllers/workoutController.js:
// DELETE workout (verwijderen)
export const deleteWorkout = async (req, res) => {
const { id } = req.params;
// Check of ID geldig is
if (!mongoose.isValidObjectId(id)) {
return res.status(400).json({ error: 'Ongeldige workout ID' });
}
try {
const workout = await Workout.findByIdAndDelete(id);
if (!workout) {
return res.status(404).json({ error: 'Workout niet gevonden' });
}
res.status(200).json(workout);
} catch (error) {
res.status(500).json({ error: error.message });
}
};
const { id } = req.params- Haal ID uit URLisValidObjectId(id)- Check ID formaatfindByIdAndDelete(id)- Zoek en verwijder in één keerif (!workout)- Niet gevonden? Stuur 404res.status(200).json(workout)- Stuur verwijderde workout als bevestiging
Waarom verwijderde workout terugsturen?
Handig om te zien wat er is verwijderd. In frontend kun je melding tonen: "Workout 'Squats' is verwijderd". Zonder data weet je alleen: "er is iets verwijderd", maar niet wat.
Kan je verwijderde workout terughalen?
Nee! Als je findByIdAndDelete() hebt uitgevoerd, is workout permanent weg. Geen "undo" knop. Daarom slim om bevestiging te vragen in frontend: "Weet je zeker dat je wilt verwijderen?"
Routes Toevoegen
Twee nieuwe controller functies, nu routes toevoegen.
Update workoutRoutes.js
Vervang volledige inhoud van src/routes/workoutRoutes.js:
// src/routes/workoutRoutes.js
import express from 'express';
import {
getAllWorkouts,
getWorkoutById,
createWorkout,
updateWorkout,
deleteWorkout
} from '../controllers/workoutController.js';
const router = express.Router();
// GET alle workouts
router.get('/', getAllWorkouts);
// GET één workout
router.get('/:id', getWorkoutById);
// POST nieuwe workout
router.post('/', createWorkout);
// PATCH workout (aanpassen)
router.patch('/:id', updateWorkout);
// DELETE workout
router.delete('/:id', deleteWorkout);
export default router;
CRUD is compleet!
Alle 4 basis operaties:
- Create - POST
- Read - GET (alle + één)
- Update - PATCH
- Delete - DELETE
Testen in Postman
Tijd om UPDATE en DELETE routes te testen!
Voorbereiding: Test data
Zorg dat je paar workouts in database hebt. Doe POST requests als je geen data hebt.
1. PATCH - Pas workout aan
Kopieer _id van bestaande workout (doe GET om ID's te zien).
PATCH http://localhost:4000/api/workouts/abc123...
Body (raw, JSON):
{
"reps": 20
}
Wat gebeurt er? Alleen reps wordt aangepast naar 20. Title en load blijven.
Response (status 200):
{
"_id": "abc123...",
"title": "Squats",
"reps": 20, // Aangepast!
"load": 50,
"createdAt": "2024-11-22T10:00:00.000Z",
"updatedAt": "2024-11-22T15:30:00.000Z" // Nieuwe tijd!
}
Let op: updatedAt is automatisch aangepast!
2. PATCH - Meerdere velden
PATCH http://localhost:4000/api/workouts/abc123...
Body (raw, JSON):
{
"reps": 15,
"load": 75,
"title": "Heavy Squats"
}
Nu worden alle drie velden aangepast!
3. PATCH - Ongeldig ID
PATCH http://localhost:4000/api/workouts/123
Body (raw, JSON):
{
"reps": 20
}
Response (status 400):
{
"error": "Ongeldige workout ID"
}
4. PATCH - Niet-bestaand ID
PATCH http://localhost:4000/api/workouts/507f1f77bcf86cd799439011
Body (raw, JSON):
{
"reps": 20
}
Response (status 404):
{
"error": "Workout niet gevonden"
}
5. DELETE - Verwijder workout
Kopieer _id van workout die je wilt verwijderen.
DELETE http://localhost:4000/api/workouts/abc123...
Let op: DELETE heeft geen body! Alleen URL met ID.
Response (status 200):
{
"_id": "abc123...",
"title": "Squats",
"reps": 10,
"load": 50,
"createdAt": "2024-11-22T10:00:00.000Z",
"updatedAt": "2024-11-22T10:00:00.000Z"
}
Dit is de workout die je net verwijderde (als bevestiging).
6. DELETE - Check of echt weg
Doe GET naar zelfde ID:
GET http://localhost:4000/api/workouts/abc123...
Response (status 404):
{
"error": "Workout niet gevonden"
}
Perfect! Workout is écht verwijderd uit database.
7. DELETE - Ongeldig ID
DELETE http://localhost:4000/api/workouts/123
Response (status 400):
{
"error": "Ongeldige workout ID"
}
Problemen oplossen
❌ PATCH geeft oude waarde terug
Probleem: { new: true } vergeten
Check updateWorkout functie:
const workout = await Workout.findByIdAndUpdate(
id,
{ ...req.body },
{ new: true } // Deze regel!
);
Zonder krijg je oude versie van voor update.
❌ PATCH verandert niets, geen error
Probleem: Geen body mee, of verkeerde veldnamen
Check:
- Postman: Body → raw → JSON geselecteerd?
- JSON syntax: aanhalingstekens rond veldnamen?
- Veldnamen:
"reps"(correct) of"rep"(fout)? - Correcte body:
{ "reps": 20, "load": 60 }
❌ DELETE geeft 404 maar workout bestaat
Probleem: Verkeerd ID gekopieerd of spatie erin
Check:
- Doe GET /api/workouts om alle ID's te zien
- Kopieer
_idprecies (zonder spaties) - Test met GET /api/workouts/:id of ID werkt voor DELETE
❌ "Cannot read property 'reps' of null"
Probleem: findByIdAndUpdate() vindt niks (geeft null), maar code probeert iets te doen met null
Check if (!workout) check:
const workout = await Workout.findByIdAndUpdate(...);
if (!workout) { // Deze check!
return res.status(404).json({ error: 'Workout niet gevonden' });
}
res.status(200).json(workout);
❌ PATCH/DELETE werkt niet in browser
Probleem: Browsers kunnen alleen GET via adresbalk
Oplossing: Gebruik Postman voor PATCH en DELETE. Je kunt ze niet testen in browser adresbalk.
Verschil PATCH vs PUT
Je gebruikt PATCH, maar wat is verschil met PUT?
PATCH - Gedeeltelijke update
Stuur alleen velden die je wilt veranderen:
{
"reps": 20
}
Resultaat: Alleen reps verandert. title en load blijven.
PUT - Volledige vervanging
Moet hele object sturen:
{
"title": "Squats",
"reps": 20,
"load": 50
}
Als je veld vergeet (bijv. load), wordt dat veld leeg of verwijderd!
Welke gebruiken we?
We gebruiken PATCH omdat dat makkelijker is voor frontend. Je hoeft niet steeds alle velden mee te sturen, alleen wat je wilt veranderen.
PUT wordt gebruikt als je écht hele object wilt vervangen, maar dat is zelden nodig.
Checklist
✅ Check of je hebt:
- updateWorkout functie in workoutController.js
- updateWorkout gebruikt findByIdAndUpdate() met { new: true }
- updateWorkout heeft ID validatie en 404 check
- deleteWorkout functie in workoutController.js
- deleteWorkout gebruikt findByIdAndDelete()
- deleteWorkout heeft ID validatie en 404 check
- Beide geëxporteerd met export const
- PATCH route: router.patch('/:id', updateWorkout)
- DELETE route: router.delete('/:id', deleteWorkout)
- PATCH werkt in Postman en past alleen meegegeven velden aan
- DELETE werkt in Postman en verwijdert écht
- Beide routes geven correcte errors bij ongeldig/niet-bestaand ID
- Je begrijpt verschil tussen PATCH en PUT
CRUD Status:
- Create - POST nieuwe workout
- Read - GET alle + GET één
- Update - PATCH workout aanpassen
- Delete - DELETE workout verwijderen
Je backend is nu klaar! Volledige REST API met alle CRUD operaties.
Volgende Stap
Backend API is compleet met alle CRUD operaties! Kies nu hoe je je frontend wilt verbinden:
Frontend verbinden met HTML/CSS/JS →
Verbind je backend met een gewone HTML/CSS/JavaScript frontend
Frontend verbinden met React →
Verbind je backend met een React frontend