[RESOLU] Valider plusieurs fois un formulaire sans actualiser la page

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : [RESOLU] Valider plusieurs fois un formulaire sans actualiser la page

Re: Valider plusieurs fois un formulaire sans actualiser la page

par jeicko » 23 avr. 2021, 16:57

Je n’ai pas réussi mais c’est pas grave c’est déjà pas mal pour un petit site comme le mien.
Tu m’as bien aidé en tout cas je te remercie, je passe le sujet en résolu.

Re: Valider plusieurs fois un formulaire sans actualiser la page

par Saian » 22 avr. 2021, 11:54

En fait la condition pour vider le champs au success ça serait plutôt if (data.error == ''), à vérifier si tu transmet une variable error à vide quand il n'y a pas d'erreur.

Perso, j'ai plutôt tendance à passer une variable succes à 0 ou 1 selon qu'il y a une erreur ou pas. Et généralement quand success est à 0 (erreur) je passe aussi une variable message avec le message d'erreur.

Ainsi dans le js j'ai un traitement du type :
success: function (data) {
    if (!data.success) {
        alert(data.message);
        return false;
    }

    // le code si la réponse est en success=1
}

Re: Valider plusieurs fois un formulaire sans actualiser la page

par jeicko » 22 avr. 2021, 11:06

Merci,

Si j'ai bien utilisé ce que tu me dis je ne vois pas d'erreurs dans ma console.
Je continue de chercher.

Re: Valider plusieurs fois un formulaire sans actualiser la page

par Saian » 22 avr. 2021, 01:58

Pourtant ça me parait pas mal dans l'idée. Tu peux utiliser console.log() pour débuguer le js. Il faut que tu utilises les outils de développement de ton navigateur (généralement onglet console pour voir les logs).
https://developer.mozilla.org/fr/docs/W ... onsole/log

Re: Valider plusieurs fois un formulaire sans actualiser la page

par jeicko » 22 avr. 2021, 00:32

Je tente des choses en vain, voici ce que j'essaie de faire, mais je ne sais pas quoi mettre entre les ""

Code : Tout sélectionner

$.ajax({ url: "add_comment.php", method: "POST", data: form_data, dataType: "JSON", success: function(data) { if (data.error !== "") { $comment_content.val('');//ici je vide seulement le le texte saisi après validation $comment_message.html(data.error); //un formulaire (élément) contient tous ses inputs //c'est rangé par nom $comment_form[0].comment_id.value = "0"; load_comment(); } },//ici j'essaie de ne pas vider le formulaire en cas d'erreurs error: function(data) { if (data.error !== "") { $comment_message.html(data.error); $comment_form[0].comment_id.value = "0"; load_comment(); } }, });

Re: Valider plusieurs fois un formulaire sans actualiser la page

par jeicko » 21 avr. 2021, 17:38

PPPS : tu pourrais également re-remplir les champs du formulaire en cas d'erreur pour que l'utilisateur n'ait pas à les re-saisir.
Après je te laisse tranquille et je clos le sujet :D

Est-ce que je dois créer un genre de condition en JS ou en PHP ou il y a plus simple ?

Re: Valider plusieurs fois un formulaire sans actualiser la page

par jeicko » 21 avr. 2021, 17:16

Quand j'ai lu ton message, je me suis dit que c'était extrêmement logique et que j'aurais pu le trouver tout seul sauf que.. ça ne veut pas fonctionner, je me prends la tête dessus depuis plus d'une heure pourtant ça parait logique ce que tu me proposes.

PS : Pour tester j'ai ajouté

Code : Tout sélectionner

const $email = $("#email");
puis

Code : Tout sélectionner

$email.val('')
et ça me vide bien le mail pourtant

PPS : C'est bon j'ai trouvé, en fait il fallait que je cible #comment_content :

Code : Tout sélectionner

const $comment_content = $("#comment_content");

Code : Tout sélectionner

$comment_content.val('');

Re: Valider plusieurs fois un formulaire sans actualiser la page

par Saian » 21 avr. 2021, 14:37

Salut, alors oui c'est une bonne idée au départ sauf que dans ton cas précis le formulaire est remis à 0 via le javascript ($comment_form[0].reset();).
Au lieu de remettre tout le formulaire à 0, vide seulement le champ message.

Par exemple tu peux faire un $comment_message.val('');

Re: Valider plusieurs fois un formulaire sans actualiser la page

par jeicko » 21 avr. 2021, 13:29

PPPS : tu pourrais également re-remplir les champs du formulaire en cas d'erreur pour que l'utilisateur n'ait pas à les re-saisir. De même tu pourrais remettre le pseudo et le mail saisis lors du premier envoi.
Ça m’a donné envie de pousser un peu la chose.. pour la 1ère étape je ne sais pas trop par où commencer mais pour remettre le pseudo et le mail saisis lors du premier envoi je dois passer ma page .html en .php pour faire quelque chose de ce type ?

Code : Tout sélectionner

<form method="post" action="test.php"> <input type="text" name="exemple" value="<?php if (isset($_POST['exemple'])){echo $_POST['exemple'];} ?>" /> <input type="submit" value="envoyer" /> </form>
Ou je fais fausse route ?

Re: Valider plusieurs fois un formulaire sans actualiser la page

par jeicko » 20 avr. 2021, 18:45

Ok je pense avoir compris :

Code : Tout sélectionner

//Connexion Recaptcha grecaptcha.ready(function () { grecaptcha .execute("***", { action: "homepage", }) .then(function (token) { document.getElementById("recaptchaResponse-com").value = token; }); }); $(document).ready(function() { //quand le DOM est là, on sélectionne les éléments avec lesquels on va travailler //c'est mieux de le faire une fois au début, pour des questions de perf //mais surtout pour éviter d'avoir à faire un gros ctrl + r pour changer les sélecteurs. const $comment_form = $("#comment_form"); const $comment_message = $("#comment_message"); const $display_comment = $("#display_comment"); $comment_form.on("submit", function(event) { event.preventDefault(); const form_data = $comment_form.serialize(); $.ajax({ url: "add_comment.php", method: "POST", data: form_data, dataType: "JSON", success: function(data) { if (data.error !== "") { $comment_form[0].reset(); $comment_message.html(data.error); //un formulaire (élément) contient tous ses inputs //c'est rangé par nom $comment_form[0].comment_id.value = "0"; load_comment(); } }, }); //on renouvelle le token pour envoyer un 2nd commentaire grecaptcha .execute("***", { action: "homepage", }) .then(function (token) { document.getElementById("recaptchaResponse-com").value = token; }); }); reload(); ////////////////////////////////// function load_comment() { $.ajax({ url: "fetch_comment.php", //POST pour envoyer des données, et GET pour obtenir des données method: "POST", success: function(data) { $display_comment.html(data); $(".reply").on("click", function() { $comment_form[0].comment_id.value = $(this).attr("id"); $comment_form[0].comment_name.focus(); }); }, }); } function reload() { load_comment(); setTimeout(reload, 10000); } });


Pour le formulaire de contact (que j'ai fait il y a bien longtemps) le code n'était pas fait de la même façon, j'ai suivi le même principe, ça fonctionne mais je me permets de te le montrer aussi dans le doute car pour moi, le JS et PHP n'est pas aussi fluide que toi, j'ai peur de faire une bourde. Si t'as 5min pour regarder je te remercie.

Code : Tout sélectionner

$("#contact-form").submit(function (event) { event.preventDefault(); // Empêcher la soumission directe du formulaire $("#alert").text("Envoi en cours...").fadeIn(0); // Afficher "Traitement" pour informer l'utilisateur que le formulaire est en cours d'envoi grecaptcha.ready(function () { // Clef REcaptcha site ci dessous grecaptcha .execute("***", { action: "contact", }) .then(function (token) { var recaptchaResponse = document.getElementById("recaptchaResponse"); recaptchaResponse.value = token; // Passez l'appel Ajax ici $.ajax({ url: "contact.php", type: "post", data: $("#contact-form").serialize(), dataType: "json", success: function (_response) { // La requête Ajax est un succès. _response est un objet JSON var error = _response.error; var success = _response.success; if (error != "") { // En cas d'erreur, affichez-le à l'utilisateur $("#alert").html(error); } else { // En cas de succès, affichez-le à l'utilisateur et supprimez le bouton d'envoi (non utilisé pour le moment) $("#alert").html(success); $("").remove(); $("#contact-form")[0].reset(); } }, error: function (jqXhr, json, errorThrown) { // En cas d'erreur Ajax également, affiche le résultat var error = jqXhr.responseText; $("#alert").html(error); $("#contact-form")[0].reset(); }, }); //on renouvelle le token pour envoyer un 2nd message grecaptcha .execute("***", { action: "contact", }) .then(function (token) { document.getElementById("recaptchaResponse").value = token; }); }); }); });

Re: Valider plusieurs fois un formulaire sans actualiser la page

par Saian » 20 avr. 2021, 17:35

Je l'aurais plutôt mis après le $.ajax du add_comment que dans la callback success mais sinon c'est ça oui. En le mettant après le $.ajax, le recaptcha est renouvelé parallèlement à la soumission du message si je puis dire, alors qu'en le mettant dans la callback success, il n'est renouvelé que s'il y a un retour en succès à la soumission du formulaire. Et oui dans l'idée, pareil pour le formulaire de contact.

Re: Valider plusieurs fois un formulaire sans actualiser la page

par jeicko » 20 avr. 2021, 17:16

PPPS : tu pourrais également re-remplir les champs du formulaire en cas d'erreur pour que l'utilisateur n'ait pas à les re-saisir. De même tu pourrais remettre le pseudo et le mail saisis lors du premier envoi.
Alors j'aimerais pouvoir ajouter toutes ces fonctionnalités mais honnêtement je n'ai pas les bases et je ne sais pas le faire..
PPS : autre solution, au lieu de déplacer le code comme je le suggère plus haut, lors de la soumission du formulaire tu renouvelles le token après le call ajax (tu refais le même appel que dans le grecaptcha.ready()). L'idéal serait de verrouiller le bouton d'envoi tant que le token n'est pas renouvelé.
Est-ce que tu pourrais me dire si ça doit ressembler à ça ? Je ne suis pas sûr de moi mais en tout cas l'envoi de plusieurs messages d'affilé fonctionne :

Code : Tout sélectionner

//Connexion Recaptcha grecaptcha.ready(function () { grecaptcha .execute("***", { action: "homepage", }) .then(function (token) { document.getElementById("recaptchaResponse-com").value = token; }); }); $(document).ready(function () { //quand le DOM est là, on sélectionne les éléments avec lesquels on va travailler //c'est mieux de le faire une fois au début, pour des questions de perf //mais surtout pour éviter d'avoir à faire un gros ctrl + r pour changer les sélecteurs. const $comment_form = $("#comment_form"); const $comment_message = $("#comment_message"); const $display_comment = $("#display_comment"); $comment_form.on("submit", function (event) { event.preventDefault(); const form_data = $comment_form.serialize(); $.ajax({ url: "add_comment.php", method: "POST", data: form_data, dataType: "JSON", success: function (data) { if (data.error !== "") { $comment_form[0].reset(); $comment_message.html(data.error); //un formulaire (élément) contient tous ses inputs //c'est rangé par nom $comment_form[0].comment_id.value = "0"; load_comment(); //on renouvelle le token pour envoyer un 2nd commentaire grecaptcha .execute("***", { action: "homepage", }) .then(function (token) { document.getElementById("recaptchaResponse-com").value = token; }); } }, }); }); reload(); ////////////////////////////////// function load_comment() { $.ajax({ url: "fetch_comment.php", //POST pour envoyer des données, et GET pour obtenir des données method: "POST", success: function (data) { $display_comment.html(data); $(".reply").on("click", function () { $comment_form[0].comment_id.value = $(this).attr("id"); $comment_form[0].comment_name.focus(); }); }, }); } function reload() { load_comment(); setTimeout(reload, 10000); } });
PS : pour le formulaire de contact tu auras surement le même problème si l'utilisateur veut envoyer plusieurs messages et qu'il ne rafraichit pas la page entre temps.
Je dois donc appliquer le même principe que le precedent code (dans l'éventualité ou le code est juste)

Re: Valider plusieurs fois un formulaire sans actualiser la page

par Saian » 20 avr. 2021, 16:23

Je viens de regarder et donc c'est bien le même token lors des deux appels. Je pense que tu dois avoir une erreur lors du deuxième verify parce que c'est le même token.

Le code que tu as mis dans le grecaptcha.ready() tu devrais le basculer dans le submit du formulaire et tu mets la soumission ajax dans le then().

Sinon la page est très propre.

PS : pour le formulaire de contact tu auras surement le même problème si l'utilisateur veut envoyer plusieurs messages et qu'il ne rafraichit pas la page entre temps.

PPS : autre solution, au lieu de déplacer le code comme je le suggère plus haut, lors de la soumission du formulaire tu renouvelles le token après le call ajax (tu refais le même appel que dans le grecaptcha.ready()). L'idéal serait de verrouiller le bouton d'envoi tant que le token n'est pas renouvelé.

PPPS : tu pourrais également re-remplir les champs du formulaire en cas d'erreur pour que l'utilisateur n'ait pas à les re-saisir. De même tu pourrais remettre le pseudo et le mail saisis lors du premier envoi.

Re: Valider plusieurs fois un formulaire sans actualiser la page

par jeicko » 20 avr. 2021, 16:10

Je vais regarder tout ce que tu me dis en detail, mais je me sens un peu dépassé là.

Je te mets l'url de mon site ou je fais les tests si jamais tu veux voir comment ça fonctionne : lien supprimé

N'hesite pas à utiliser les formulaires ça ne pose pas de problème

Re: Valider plusieurs fois un formulaire sans actualiser la page

par Saian » 20 avr. 2021, 15:51

Sans voir les codes ou sans voir ce que fait la page je ne tirerais aucune conclusion. Déjà as tu vérifié que tu as bien quelque chose dans $_POST['recaptcha-response'] pour chaque appel ? et si oui est ce que c'est un token différent où est ce que c'est toujours le même ? Dans le cas où tu as une erreur as tu regarder en détail le retour du call curl pour voir si tu n'as pas une erreur détaillée de l'api recaptcha ? parce que la tu ne fais qu'un if ($data->score >= 0.5) alors que la réponse peut contenir des codes d'erreur, tu as peut être une erreur timeout-or-duplicate par exemple.

La pour moi en parcourant vite fait ton code, j'imagine que l'input hidden est définit automatiquement lors du chargement de la page et qu'ensuite il ne bouge plus. Et je suppose que le token est a usage unique, raison pour laquelle ça ne fonctionnerait qu'une fois. Peut être as tu un code quelque part que tu n'as pas dévoilé ou que je n'ai pas vu où l'input hidden est renseigné suite à un call javascript avec l'api recaptcha ?

PS : sinon inspire toi de l'exemple "Programmatically invoke the challenge" de la doc.

Je te remets les liens, à priori y a tout ce qu'il faut dedans.
https://developers.google.com/recaptcha/docs/v3
https://developers.google.com/recaptcha/docs/verify