Bonjour,
Je suis en train de travailler sur un gestionnaire d'habilitation qui va permettre aux utilisateurs enregistrés d'accéder à une ou plusieurs applications en ligne.
J’ai créé un formulaire qui permet de sélectionner un utilisateur d'autoriser son accès à une application web.
Le formulaire est on ne peut plus simple et tous les échanges avec la base de données s’effectuent avec AJAX.
Dans mon formulaire j'ai :
Un évènement attaché à un menu déroulant (bootstrap-select) qui permet de sélectionner un utilisateur et de récupérer de la table sql des utilisateurs les informations dont j'ai besoin.
<div class="container">
<h1>Ajouter un utilisateur</h1>
<div id="addform" class="col-lg-6">
<form action="#" class="form-horizontal" enctype="application/x-www-form-urlencoded">
<div class="form-group">
<label class="control-label col-lg-4" for="identite">Identifiant : </label>
<div class="col-lg-8">
<select id="idselection" class="selectpicker" data-live-search="true" title="Matricule/Nom" data-width="auto">
<option selected disabled ></option>
<?php foreach ($userslist as $item): ?>
<option value="<?= $item->matricule; ?>" ><?= $item->nom; ?> <?= $item->prenom; ?> <?= $item->matricule; ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
</form>
<div id="user" data-app="<?= is_numeric($this->request->params[0]) ? $this->request->params[0] : null; ?>"></div>
</div>
</div>
Le résultat de la requête est affiché dans le div#user par chargement d'un fichier php userprofile.php dans lequel j'insère les informations :
<div class="userprofilebox">
<div class="input-group">
<span class="input-group-addon">NOM : </span>
<p id="nom" class="form-control"></p>
</div>
<div class="input-group">
<span class="input-group-addon">PRENOM : </span>
<p id="prenom" class="form-control"></p>
</div>
<div class="input-group">
<span class="input-group-addon">MATRICULE : </span>
<p id="matricule" class="form-control"></p>
</div>
<div class="input-group">
<span class="input-group-addon">SERVICE : </span>
<p id="service" class="form-control"></p>
</div>
<div class="row">
<button id="validate" class="btn btn-success" type="button" value="" ><span class="glyphicon glyphicon-ok"></span> Habiliter</button>
<a class="btn btn-danger" href="<?= WEBROOT; ?>/app/liste" target="_parent" title="Retour à la liste des applications" ><span class="glyphicon glyphicon-remove"></span> Abandon</a>
</div>
</div>
..et je clique sur le bouton Habiliter pour enregistrer cette nouvelle habilitation.
$(function () {
// Selection de l’utilisateur
$("#idselection").on('changed.bs.select', function (e) {
var identifiant = $(this).val();
function reponse(callback) {
$.ajax({
url: "applications/activedirectory/PHPScripts/ajax-get-user", // requete sur table des utilisateurs
method: "post",
data: {ref: identifiant},
dataType: 'JSON'
})
.done(function (data, textStatus, jqxhr) {
callback(data);
})
.fail(function (jqxhr) {
callback(jqxhr.responseText);
});
}
// Resultat de la requet est affiché dans la page userprofile.php chargée dans un div (J'avais la flême de générer du DOM)
reponse(function (data) {
var app = $("#user").data('app');
$("#user")
.load('userprofile', function (e) {
$(this).find('#nom').text(data.nom);
$(this).find('#prenom').text(data.prenom);
$(this).find('#matricule').text(data.matricule);
$(this).find('#service').text(data.service);
$(this).find('#validate').attr('value', data.matricule); // Bouton de validation
})
// Click sur le bouton de validation
.on('click', 'button#validate', function (e) {
function calling(callback) {
// Requete INSERT dans la table des habilitations
$.ajax({
url: "applications/activedirectory/PHPScripts/ajax-add-user",
method: "post",
data: {app: app, ref: identifiant},
dataType: 'JSON'
})
.done(function (data, textStatus, jqxhr) {
callback(data);
})
.fail(function (jqxhr) {
callback(jqxhr.responseText);
});
}
// Affichage d’un message (erreur ou succès)
calling(function (data) {
var msg = "<div class='col-lg-12 alert alert-info'>";
msg += "<button type='button' class='close' aria-label='Close' data-dismiss='alert'><span aria-hidden='true'>×</span></button>";
msg += "<h4>Message</h4>";
msg += "<p>" + data +"</p>";
msg += "</div>";
$("#user").before(msg);
});
});
});
})
});
Tous fonctionne à merveille (hormis les messages mais ça c'est un détail) ! Sauf… que dans la console du navigateur (network onglet XHR) je vois apparaître l’impensable ! l’inimaginable !
Dans mon formulaire je sélection un utilisateur, les informations s'affichent, je clique sur le bouton button#validate, il est enregistré dans la table des utilisateurs habilités.
Je continue, je sélectionne un autre utilisateur, les informations de ce nouvel utilisateur remplacent les précédentes, je clique sur le bouton button#validate, il est enregistré.
etc.. donc je suis content !
MAIS !
Voilà ce qu'il se passe lorsque je surveille l'activité dans la console du navigateur -> network onglet XHR
Premier utilisateur : une requête vers ajax-add-user.php
Deuxième utilisateur : je vois 2 requêtes vers ajax-add-user.php ( le premier utilisateur suivi du second)
Troisième : je vois 3 requêtes vers ajax-add-user.php… (le premier suivi du second lui-même suivi du troisième).
etc..
Bon, j’ai cherché avant de poster sur le forum mais là… je donne ma langue au chat.
Jquery bubble ? Heu non j’pense pô.
Ma seule piste c’est la délégation du click sur le bouton #validate.
Pour l'heure j'ai réecrit le code jquery différement en séparant les contenus de l'évenement change et click
$(function(){
$("#idselection").on('changed.bs.select', function (e) {...}
$(#user).on('click', 'button#validate', function (e) {..}
});
C'est moche mais ça fonctionne aussi.
Si quelqu'un pouvait m'expliquer d'ou vient cette démultiplication du contenu de l'évènement CLICK, ça serait simpa :)
Hello, cet article résume tout à fait le comportement du bug et pourquoi ton changement a résolu le problème.https://triangle717.wordpress.com/2015/12/14/js-avoid-duplicate-listeners/
C'est parce que dans tu ajoutes un listener sur click
a chaque fois dans ton callback de reponse()
.
Bonjour et merci de ta réponse !
Cela je m'en doutais un peu ("Ma seule piste c’est la délégation du click sur le bouton #validate.") mais ce que j'ignore c'est le comment du pourquoi. A chaque selection d'un nouvel utilisateur les variables destinées à transmettre les données en POST par AJAX sont réinitialisées non ? Comment se peut il que les réponses AJAX précédentes soient toujours rappelées lors d'une nouvelle excution du code ? C'est ça que je ne comprend pas...
Définit ton évènement click une seule fois et utilise des variables...
Si tu ne connais rien à javascript arrête d'utiliser jquery -_-
Apprends js et ensuite tu pourras légitimement, facilement et de façon transparente te "faciliter" la vie avec jquery ou n'importe quel autre framework..!
Merci prbaron, voilà une réponse tout à fait productive et qui va me permettre d'avancer dans mon apprentissage !
Psylozoff, je me passerais volontier de ce genre de commentaires d'autant que la solution ne m'intéresse pas, mais plutôt une piste de reflexion , un lien vers un article, afin comprendre mon erreur.
Tu dis que tu ne comprends pas la notion de "gestionnaire d'évènement" qui est pourtant une des bases fondamentales de javascript ^^
Or, tu nous présentes du jQuery : un framework qui occulte la majeure partie de la logique applicative de JS :-s
Je te dis juste que tu essaies de comprendre le fonctionnement d'un moteur en regardant la carrosserie...