11484 sujets

JavaScript, DOM et API Web HTML5

Bonjour à tous !

J'ai une page html qui contient 2 inputs non déclarés dans un formulaire (aucun formulaire dans la page). J'ai également un bouton déclaré sous forme de div.

Un addEventListener me permet d'appeler une fonction au clic sur le bouton.

Voici le contenu du fichier js :

const bigFile = document.getElementById('bigFile').files[0]; // Le 1er input
const smallFile = document.getElementById('smallFile').files[0]; // Le 2e input

const button = document.getElementById('button'); // Le bouton
button.addEventListener('click', (e) => {
    e.preventDefault();
    ajout();
})

function ajout() {
    if (bigFile || smallFile) {
        if (!bigFile) {
            alert('Vous devez charger 2 fichiers image');
        }
        if (!smallFile) {
            alert('Vous devez charger 2 fichiers image');
        }

        const fdata = new FormData();
        fdata.append('imageUrlBig', bigFile);
        fdata.append('imageUrlSmall', smallFile);
        console.log(fdata);
 
        const head3 = {
            method: 'POST',
            body: fdata,
            headers: {'Authorization': `Bearer ${sessionStorage.token}`}
        }

        fetch('http://localhost:4000/api/caroussel/', head3)
            .then(reponse => {
                if (reponse.status == 201) {
                    alert('Nouvelles images ajoutées avec succès !')
                }
                else {
                    return reponse.json({message: "ça ne fonctionne pas"});
                }
            })
            .catch(e => {
                console.log("ça n'a pas marché...")
            })
    }
}


Ce qui se passe c'est qu'au clic, le fetch s'exécute bien (le back reçoit bien les fichiers) mais la page se recharge avant d'afficher l'alert et le fetch semble être re-exécuté car la console affiche "ça n'a pas marché..." après rechargement. Pourtant côté back je n'ai aucune erreur, tout a fonctionné correctement.
Comme vous pouvez le voir j'ai mis un e.preventDefault() sur le listener mais ça ne change rien.

Vous avez une idée de ce qui se passe ?
Merci d'avance pour votre aide !
Modifié par Vahia (20 Jan 2023 - 02:51)
Le fetch ne cause pas le reload de la page. c'est impossible. ça vient donc d'ailleurs.

Tu as surement mit un bouton submit qui lui recharge par contre.
Smiley smile Je suis bien d'accord avec toi et c'est ça qui me déroute.
La page html est très basique : une div dans laquelle il y a 2 inputs de type file et une div qui fait office de bouton. Pas de form, pas de submit, de button, etc...
Bah là, impossible de t'aider. on a pas tout le code html, tout le code JS. désolé.. en plus tu nous dit que tu n'a pas de form.. difficile de croire au vu de la ligne FormData() ...

En tout cas je te confirme, le fetch ne reload pas la page.
J'ai utilisé formData pour pouvoir passer des fichiers dans ma requête. Je n'ai pas utilisé d'élément form pour autant.

Voici le code html :
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://kit.fontawesome.com/5ccf739b21.js" crossorigin="anonymous" defer></script>
    <script type="text/javascript" src="./reqs.js" defer></script>
</head>
<body>
    <div class="ajout">
        <h2 class="containers__first--title">Ajouter des nouvelles images</h2>
        <div class="ajout__files">
            <div id="big" class="ajout__files--big">
                <p class="ajout__files--text">Image pour grands écrans<i class=" ajout__files--arrow fa-solid fa-arrow-right-long"></i></p>
                <span class="infobulle infobulle--deuxio">Recadrer en 1920x700 et privilégier le format webp (jpg et png acceptés).</span>
            </div>
            <div id="small" class="ajout__files--small">
                <p class="ajout__files--text">Image pour petits écrans<i class=" ajout__files--arrow fa-solid fa-arrow-right-long"></i></p>
                <span class="infobulle infobulle--deuxio">Recadrer en 650x490 et privilégier le format webp (jpg et png acceptés).</span>
            </div>
        </div>
    </div>
    <div class="cards cards__type1 ajout__files__butt" id="button">Enregistrer<br>les modifications</div>
</body>
</html>


et voici le javascript :
const big = document.getElementById('big');
const inputBig = document.createElement('input');
inputBig.id = 'bigFile';
inputBig.className = 'ajout__files--input ajout__files--input--big';
inputBig.setAttribute('type', 'file');
inputBig.setAttribute('accept', '.jpeg, .jpg, .png, webp');
big.appendChild(inputBig);
const small = document.getElementById('small');
const inputSmall = document.createElement('input');
inputSmall.id = 'smallFile';
inputSmall.className = 'ajout__files--input ajout__files--input--small';
inputSmall.setAttribute('type', 'file');
inputSmall.setAttribute('accept', '.jpeg, .jpg, .png, webp');
small.appendChild(inputSmall);


const headerGet = {
    method: 'GET',
    headers: {'Content-Type': 'application/json'}
};

const button = document.getElementById('button');
    button.addEventListener('click', (e) => {
        e.preventDefault();
        ajout();
    });

function ajout() {
    const bigFile = inputBig.files[0];
    const smallFile = inputSmall.files[0];
    if (bigFile || smallFile) {
        if (!bigFile) {
            alert('Vous devez charger 2 fichiers image');
        }
        if (!smallFile) {
            alert('Vous devez charger 2 fichiers image');
        }

        const fdata = new FormData();
        fdata.append('imageUrlBig', bigFile);
        fdata.append('imageUrlSmall', smallFile);
    
        const head3 = {
            method: 'POST',
            body: fdata,
            headers: {'Authorization': `Bearer ${sessionStorage.token}`}
        }

        fetch('http://localhost:4000/api/caroussel/', head3)
            .then(reponse => {
                console.log(reponse.status);
                if (reponse.status == 201) {
                    console.log('Réussi');
                    alert('Nouvelles images ajoutées avec succès !')
                }
                else {
                    return reponse.json({message: "C'est la mewde"});
                }
            })
            .catch(e => {
                console.log("ça n'a pas marché...")
            })
    }
}


On est d'accord qu'un fetch ne recharge pas la page mais du coup je me demande bien ce qui peut le déclencher...
Je viens de me renseigner :

Cette requête Fetch peut causer une recharge de la page si elle a un statut de réponse différent de 201. Il faut donc vérifier les statuts de réponse de la requête Fetch et éviter de recharger la page si nécessaire. ce que tu fais déjà... hmmm.... je cherches en parallèle
Modifié par JENCAL (25 Jan 2023 - 11:31)
ça doit venir d'ailleurs. peut être dans ton php, que le problème provienne de la réponse du serveur à ta requête Fetch. Si le serveur renvoie une réponse qui indique à la page de se recharger, cela peut causer un rechargement de la page. Vérifie les en-têtes de réponse et le contenu de la réponse pour voir s'il y a des instructions qui pourraient causer un rechargement de la page.

Il est également possible que le problème provienne d'un conflit avec d'autres scripts ou bibliothèques que tu as utilisé sur ton site. Il est important de vérifier tout le code pour s'assurer qu'il n'y a pas de conflit ou d'interférence avec d'autres scripts ou bibliothèques.

et il est important de vérifier les erreurs de la console pour voir si il y a des erreurs qui pourraient causer un rechargement de la page.
Modifié par JENCAL (25 Jan 2023 - 11:36)
oui ok, peu importe php ou node. vérifie bien de ce côté aussi Smiley smile

car avec le html / js que tu as fourni à priori ça ne vient pas de là.
Côté back-end j'ai ça :
Middleware authorise :
const jwt = require('jsonwebtoken');

// Vérification que l'utilisateur utilse un token/userId valide.
module.exports = (req, res, next) => {
    try {
        const tokenRecupere = req.headers.authorization.split(' ')[1];
        const decodedToken = jwt.verify(tokenRecupere, process.env.SECRET_WORD);
        const userId = decodedToken.userId;
        req.auth = {userId};
        if (req.body.userId && req.body.userId !== userId) {
            throw res.status(403).json({message: 'User ID incorrect.'});
        }
        else {
            next();
        }
    } catch (error) {res.status(401).json({error: error | 'Requête non authentifiée.'})}
};


Middleware multer :
const multer = require('multer');
const MIME_TYPES = {
    'image/jpg': 'jpg',
    'image/jpeg': 'jpg',
    'image/png': 'png',
    'image/bmp': 'bmp',
    'image/webp': 'webp',
    'image/tiff': 'tiff',
    'image/gif': 'gif'
};

const storage = multer.diskStorage({
    destination: (req, file, callback) => {
        callback(null, 'images');
    },
    filename: (req, file, callback) => {
        const name = file.originalname.split(' ').join('_').split('.')[0]; // Suppression des espaces et de l'extension.
        const extension = MIME_TYPES[file.mimetype];
        callback(null, name + Date.now() + '.' + extension);
    }
});

module.exports = multer({storage}).any('image');


et controller :
const Caroussel = require('../models/Caroussel');
const fs = require('fs');

exports.createCaroussel = (req, res, next) => {
    const imUrl1 = req.files[0].path;
    const imUrl2 = req.files[1].path;
    const caroussel = new Caroussel({
        imageUrlBig: imUrl1,
        imageUrlSmall: imUrl2
    });
    //console.log(caroussel);
    caroussel.save()
        .then(() => res.status(201).json({message: 'Image enregistrée dans la base avec succès !'}))
        .catch(error => res.status(400).json({error}));
};


C'est rien d'extraordinaire...