Javascript change ne s'exécute pas si l'attribut a un contrainte de visibilité

Tags: #<Tag:0x00007f9e4bd5ddb0>

Dans un objet métier, j’ai un attribut de type date visible en fonction de la valeur d’un autre attribut.
j’ai ajouté dans ressource> SCRIPT une fonction sur le change de la date.
c’est fonction n’est pas exécutée.

si l’attribut est visible tout le temps, la fonction est exécutée.

Bonjour,

Sans voir le code, j’imagine que le “change” n’est pas “bindé” correctement lorsque le champ devient visible, mais quand il n’est pas encore là ? Merci de nous montrer le morceau de SCRIPT en question.

je fais juste un console .log pour le moment et il n’est affiché que si l’attribut est visible tout le temps :

CrbFopStagiaire=(function(ui) {
    // Is it the responsive UI ?
    if (!ui) return;
    // Ajax services with current grant, menu, texts...
    var app = ui.getAjax();
    // Register the hooks for myObject
    Simplicite.UI.hooks.CrbFopStagiaire = function(o, cbk) {
        try {
            // object UI parameters = clone of the globals properties
            var p = o.locals.ui;
            // When object form is loaded in the container ctn
            p.form.onload = function(ctn, obj) {
		var dtRelaiRemu=ui.getUIField(ctn, obj, "fopStagiaireIndemniteRelaiDt");

dtRelaiRemu.ui.on("change", function() {
                	console.log("RQU dtRelai change");
                });
            };
        }
        catch(e) {
            // Thank you to isolate your scripts
            app.error("Error in Simplicite.UI.hooks.CrbFopStagiaire: "+e.message);
        }
        finally {
            // Required callback when hooks are loaded
            cbk && cbk();
        }
    };
})(window.$ui);

dans l’initupdate, quand je commente le setVisible, je passe dans le change.

		// date de relai de rémunération : affichée en fonction de la valeur de indemnité relai (pas de contrainte sinon le onchange ne fonctionne pas)
	if(this.getFieldValue("fopStagiaireIndemniteRelai")=='1' && this.getFieldValue("fopStagiaireIndemnitePe")=='1'){
		//this.getField("fopStagiaireIndemniteRelaiDt").setVisible(ObjectField.VIS_FORM);
		this.getField("fopStagiaireIndemniteRelaiDt").setRequired(true);
	}else{
		//this.getField("fopStagiaireIndemniteRelaiDt").setVisible(ObjectField.VIS_NOT);
		this.getField("fopStagiaireIndemniteRelaiDt").setRequired(false);
	}

Merci, rien d’exotique donc. Je vais essayer de reproduire votre problème.
A mon avis une date visible dynamiquement n’est pas préparée correctement et l’input est remplacé par la préparation du datetimepicker, ce qui fait perdre le binding sur l’ancien input ou quelque chose de cet ordre.

(et sinon vous pouvez poster votre code en markdown pour plus de clarté :)

```javascript

code…

```

Je ne reproduis pas le problème, la change est bien appelé même si je mets une contrainte de visibilité Front sur un champ date. L’input du champ est bien préservé par le datetimepicker donc aucun raison de perdre le “change” positionné dessus.

Il y a autre chose dans votre cas.

Exemple sur la démo, code front dans le form.onload :

				var f = $ui.getUIField(ctn, obj, "demoOrdDate");
				f.ui.on("change", function() {
					console.log("change date");
				});

Contrainte Front sur la date ; devient visible si la quantité commandée est > 1 pour qu’elle soit masquée par défaut puisque quantité=1 :

Aucun code dans les hooks back.

Dès que je passe la quantité à 2, la date devient visible et si je la modifie la console s’affiche.

la différence avec mon code c’est le $ dans $ui.getUIField(ctn, obj, “demoOrdDate”)

je refais des tests

c’est la même chose car window.$ui devient le paramètre ui dans votre script.
La différence vient surement de vos hooks back.

Dans mon test il n’y en a pas du tout, la visibilité est uniquement gérée en front.
J’aurai pu retirer le contrainte et faire également un “change” sur le champ quantité qui affiche/masque la date, c’est mieux si on veut mettre tout le code au même endroit.

j’ai l’impression qu’il y a un pb de compatibilité entre mes contraintes et mon javascript.
j’ai commenté tout le script en back et ça ne change rien.

par contre, quand je commente certaines contraintes, ça fonctionne dans certains cas …

Les contraintes de type front ajoutent également des “change”. Il faut cibler celles qui concernent ces champs en particulier pour voir ce qui est incompatible. Si vous avez des règles qui rendent l’attribut non modifiable par exemple, il n’y aura peut être pas de change invoqué.

Les contraintes front peuvent s’écrire en javascript pour mieux maîtriser l’ordre d’exécution des règles / centraliser le code si elles sont trop nombreuses.

Si je comprends votre besoin plus haut ça donnera :

p.form.onload = function(ctn, obj) {
  var rl = $ui.getUIField(ctn, obj, "fopStagiaireIndemniteRelai");
  var pe = $ui.getUIField(ctn, obj, "fopStagiaireIndemnitePe");
  var dt = $ui.getUIField(ctn, obj, "fopStagiaireIndemniteRelaiDt");

  dt && dt.ui.on("change", function() {
    console.log("change date");
  });

  function rule1() {
    if (dt && dt.ui) // présent dans le formulaire
      dt.ui.visible(rl.ui.val()=="1" && pe.ui.val()=="1");
  )
  rl && rl.ui.on("change", rule1);
  pe && pe.ui.on("change", rule1);
};

j’ai trouvé le code qui fait que ça ne fonctionne pas :
je fais un dtRelaiRemu.ui.visible(relaiRemu.ui.val()==“1” && remuPe.ui.val()==“1”) et un dtRelaiRemu.ui.required(relaiRemu.ui.val()==“1” && remuPe.ui.val()==“1”)

c’est le ui.required qui fait qu’on ne passe pas dans le change de la date …

Les verbes “ui.required” et “ui.visible” rechargent tout l’input car l’affichage peut être totalement impacté. Ca explique pourquoi votre “change” ne s’applique plus car ce n’est plus le même “input”.

Donc il faut remettre votre “change” juste après si un nouveau field est créé, par exemple :

$(dt.ui.input).addClass("js-mychange");
dt.ui.visible(rl.ui.val()=="1" && pe.ui.val()=="1");
// new input on form ?
dt = $ui.getUIField(ctn, obj, "fopStagiaireIndemniteRelaiDt");
if (!($(dt.ui.input).hasClass("js-mychange"))) {
  $(dt.ui.input).addClass("js-mychange");
  dt.ui.on("change", ...); // rebind
}

Depuis les versions récentes de jQuery, il n’est plus possible de tester/récupérer les events d’un élément pour les mettre sur un autre par exemple. C’est assez problématique, seul un clone peut recopier les events, mais dans notre cas un champ n’a justement pas du toujours le même rendu suivant s’il est obligatoire, visible, en lecture seule…

Le seul moyen est de tester la présence d’une classe pour savoir si un event est déjà présent ou pas: dans l’exemple on ajoute la classe js-mychange sur l’input quand on lui bind un “change”.