Dans cette partie, on va s’occuper de la partie backend (express) afin d’ajouter des routes sur l’application.

Connexion à l’API REST

backend/app.js

const express = require('express');
const mongoose = require('mongoose');

const ingredientRoutes = require('./routes/ingredient');

const app = express();

mongoose.connect('mongodb://127.0.0.1:27017/shoppinglist')
.then(() => console.log('Connection à MongoDB réussie'))
.catch(() => console.log('Connection à MongoDB échouée'))

app.use(express.json());

app.use((req, res, next) => {
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content, Accept, Content-Type, Authorization');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
    next();
});

app.use('/api/ingredient', ingredientRoutes);

app.get("/", (req, res) => {
    res.send("test")
    console.log('test')
})

Ce fichier est le point d’entrée principal de l’application backend Express connectée à MongoDB. Il prépare la base d’une API REST Express/MongoDB : il gère la connexion, le format des données, la sécurité CORS et la structure des routes pour le module « ingredient ».

  1. Initialiser un serveur Express pour gérer les requêtes HTTP.
  2. Connecter l’application à une base MongoDB nommée shoppinglist.
    • Affiche en console le succès ou l’échec de la connexion.
  3. Activer le support JSON pour parser automatiquement le corps (body) des requêtes en JSON.
  4. Gérer les en-têtes CORS (Cross-Origin Resource Sharing) pour accepter les requêtes provenant d’autres domaines (ex : ton frontend Angular pendant le développement).
  5. Définir et activer les routes principales :
    • Les requêtes vers /api/ingredient sont déléguées au fichier de routes ingredientRoutes (qui va gérer les actions CRUD pour les ingrédients).
    • Une route GET sur / retourne simplement « test » pour vérifier que le serveur fonctionne.
  6. Exporter l’application pour qu’elle puisse être utilisée dans un fichier de démarrage (par exemple server.js).

Gérer les enregistrements dans le controlleur

backend/controllers/ingredient.js

const Ingredient = require('../models/ingredient');

exports.getAll = (req, res) => {
    Ingredient.find()
        .then(ingredients => res.status(200).json({ingredients}))
        .catch(error => res.status(400).json({error}));
}

exports.addIngredient = (req, res) => {
    console.log(req.body)
    delete req.body._id;
    const ingredient = new Ingredient({
        ...req.body
    })

    ingredient.save()
        .then(() => res.status(200).json({message: 'Ingrédient ajouté en base'}))
        .catch(error => res.status(400).json({error}));
}

Ce contrôleur gère la récupération (GET) et la création (POST) des ingrédients via Express et Mongoose : il interagit avec la base MongoDB, formate les réponses pour le frontend, et gère les erreurs courantes lors des opérations CRUD (Create/Read).

exports.getAll

  • But : Récupérer tous les ingrédients de la base MongoDB.
  • Fonctionnement : Utilise la méthode find() du modèle Mongoose pour obtenir la liste complète des ingrédients.
  • Réponse : Retourne en JSON la liste d’ingrédients si tout va bien (code 200). Sinon, un objet erreur (code 400).

exports.addIngredient

  • But : Ajouter un nouvel ingrédient à la base MongoDB.
  • Fonctionnement :
    • Affiche le corps reçu dans la requête (req.body) pour déboguer.
    • Supprime la propriété _id (car MongoDB la crée automatiquement à l’ajout).
    • Crée une nouvelle instance du modèle Ingredient avec les données reçues.
    • Sauvegarde l’objet en base avec save().
  • Réponse : Retourne un message de succès (code 200) ou un objet erreur (code 400).

Création des routes

backend/routes/ingredient.js

const express = require('express');
const router = express.Router();

const ingredientController = require('../controllers/ingredient');

router.get('/all', ingredientController.getAll);
router.post('/', ingredientController.addIngredient);

module.exports = router;

Ce fichier organise les points d’accès (routes) pour les opérations sur les ingrédients dans Express, en reliant chaque chemin HTTP à la méthode appropriée du contrôleur. Cela structure l’API et facilite la gestion du module ingredient dans le backend.

  • Création d’un routeur Express 
    C’est un objet spécialisé pour organiser les routes dédiées aux ingrédients.
  • Connexion au contrôleur (où sont définies la logique des opérations CRUD)
  • Définition des routes :
    • GET /all appelle la méthode getAll du contrôleur, qui retourne tous les ingrédients stockés.
    • POST / appelle la méthode addIngredient, qui ajoute un nouvel ingrédient à la base de données.
  • Export du routeur 
    Ce routeur pourra ensuite être utilisé dans la structure principale de l’appli (typiquement avec app.use('/api/ingredient', ingredientRoutes);).

Activer le service HttpClient

frontend/shopping-list/src/app/app.config.ts

import { routes } from './app.routes';
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
import { provideHttpClient } from '@angular/common/http';

export const appConfig: ApplicationConfig = {
  providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideAnimationsAsync(), provideHttpClient()]
};

Afin de permettre à une application Angular de faire des requêtes HTTP (GET, POST, PUT, DELETE…) vers des APIs ou des serveurs externes, il faut activer le service HttpClient.

Cet import permet d’utiliser toutes les fonctionnalités HTTP (appel d’API, récupération de données, envoi de formulaires…) en Angular en activant le client HTTP natif du framework.

  • Il configure Angular pour que le service HttpClient soit injecté et accessible partout dans l’app.
  • Avec l’approche moderne standalone, on l’ajoute dans la configuration des providers (ex : dans le fichier app.config.ts ou lors du bootstrap via bootstrapApplication), à la place du traditionnel module HttpClientModule.
  • Une fois activé grâce à ce provider, on injecte HttpClient dans les services ou composants pour communiquer facilement avec le backend.

“Ces notes techniques sont à but informatif, non formatif, et reflètent mon expérience à la date de rédaction.”