Utilisation de contrainte pour gérér les changements de valeur d'un attribut

Bonjour,

je voudrais savoir s’il est possible d’utiliser les contraintes pour gérér les changement de valeur d’un attribut.
Je m’explique :
j’ai un attribut gdrResaDemandeur et un attribut gdrResaDemandeurMail
Par défaut, à la création de la résa, le demandeur est l’utilisateur connecté. Mais il peut être changé.
Dans ce cas, je voudrais que l’attribut resaDemandeurMail soit vidé.

J’ai voulu utiliser une contrainte avec comme expression :
!(obj.getField(“gdrResaDemandeur”).getValue()).equals(obj.getField(“gdrResaDemandeur”).getOldValue());

ça ne fonctionne pas.
Comment faire avec les contraintes ?

Si le code doit être exécuté en Front il faut une syntaxe javascript (‘equals’ est un verbe java, il faut plutôt utiliser == qui marchera en back java-scripté et en front javascript).

Je vais essayer de faire un essai de comparaison old/value pour déclencher une contrainte, ça ne devrait pas poser de pb. Sinon il faudra ajouter un hook front sur le onchange du champ demandeur.

Dans la condition il faut mettre :

obj.getFieldValue("myfield")!=obj.getFieldOldValue("myfield")

Attention , en front tous les verbes java n’ont pas été implémentés dans l’objet Ajax. Seul les accesseurs principaux ont été reproduits (hasResponsibility, get/setFieldValue…) pour permettre de faire les contraintes courantes.

ça fonctionne mais j’ai un message d’erreur : Service error: too much recursion

dans ma contrainte, j’ai mis : objj.getFieldValue(“gdrResaFrequence”)!=obj.getFieldOldValue(“gdrResaFrequence”)

et dans l’impact, j’ai sélectionné Valeur du champ et j’ai mis expression : 0 (mon champs est un entier)

Il y a aussi la méthode plus simple hasChanged qui permet de comparer l’ancienne et nouvelle valeur en fonction du type (texte, number, enum, doc…)

obj.getField("myfield").hasChanged()

Mais je ne vois pas pourquoi il y aurait une boucle infinie (onchange en boucle), il doit y avoir une autre contrainte qui fait une action qui en déclenche une autre en boucle… On ne peut pas par exemple faire une contrainte qui si sa valeur change, change sa propre valeur.

Au debugger Chrome, mettez un point d’arrêt sur le handler onchange de chaque champ contraint pour voir pourquoi il y a une boucle.

c’est bon j’ai réussi à m’en sortir.

si vous pouvez ajouter ces exemples dans les tutos, ça serait très utile pour tous les utilisateurs je pense :slight_smile:

@Abed @Francois pour mémoire on a eu le même pb de stack overflow coté client avec une contrainte qui force la valeur d’un champ (genre boucle infinie sur l’event change du champ en question)

Ok mais il faut nous donner toute(s) la(les) contrainte(s) en question pour investiguer.

A la base mettre un “change” sur un champ qui refait quelque part en bout de chaine un autre “change” sur ce champ par code ou par l’intermédiaire de contraintes, c’est comme faire un while(1) dans son code, indétectable sauf à mettre un garde fou sur l’appel des contraintes limitée à 1000… mais cela ne résoudra pas le pb de conception de la règle métier, je préfère ne rien changer et laisser un “stack overflow” rejeter le traitement demandé en boucle lors du dev.

En fait dans mon cas l’impact de la contrainte qui porte sur le champ ceChamp est du genre [VALUE:unAutreChamp] == "XXX" ? "YYY" : [VALUE:ceChamp] (NB: dans ce cas particulier il n’est pas idéal de mettre la condition au niveau de la contrainte car il y a une “condition principale” au niveau de la contrainte et N impacts de nature différente avec des “sous conditions” différentes)

En fait le test supplémentaire à faire au niveau de la valorisation du champ c’est peut être de ne pas forcer la valeur si c’est la même, ça éviterait peut être de déclencher un event change qui part en boucle infinie…

La condition est dans la valeur, donc là il s’agit de remettre la valeur actuelle sous certaines conditions.
Effectivement le moteur peut vérifier que la valeur dans la contrainte est bien différente de l’actuelle.

J’espère qu’on n’a pas des cas où il faille justement “forcer” un change même si la valeur est identique.
A mon avis non, donc j’ai poussé cette évolution.

OK super. Au pire si on veut forcer un change on peut toujours le faire explicitement par API JS client (le faire en forçant une valeur à elle même par contrainte front n’est pas une bonne approche de toute façon).

je pense que mon problème venait de l’utilisation de equals.

D’où ma suggestion de compléter les tutos pour savoir ce qui est implémenté ou pas.

Il n’y a rien de spécifique à Simplicité vis à vis de ce que fait nativement Rhino (cf. https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino/Documentation).

Le piège classique de Rhino c’est entre des objets/arrays Java et des objets/arrays natifs JavaScript Rhino

Typiquement en 4.0 avec un Rhino 1.7.8 à jour on a:

var a = new java.lang.String("hello"); // a est un objet String Java
var b = "hello"; // b est un objet natif string javascript
console.log(a.equals(b)); // true
console.log(b.equals(a)); // true
console.log(a == b); // true
console.log(a === b); // false (car les 2 objets ne sont pas de même type)

Visiblement le support du equals est meilleur qu’il ne l’était avec des versions plus anciennes de Rhino

Il y a des infos sur les pièges Rhino/Java dans https://www.simplicite.io/resources/documentation/01-core/basic-code-examples.md au § “JavaScript engine traps”

Et avec les types numérique, booléen, … on a des comportements subtils:

var x = new java.lang.String("10");
var y = "10";
var z = 10;
console.log(x.equals(y)); // true
console.log(y.equals(x)); // true
console.log(x == y); // true
console.log(x === y); // false
console.log(x.equals(z)); // false
console.log(x == z); // true
console.log(x === z); // false
console.log(y.equals(z)); // true
console.log(y == z); // true
console.log(x === z); // false
//console.log(z.equals(x ou y)) => erreur
var x = new java.lang.Integer(10);
var y = 10;
console.log(x.equals(y)); // false
console.log(x == y); // true
console.log(x === y); // false
//console.log(y.equals(x)); => erreur
var x = new java.lang.Boolean(true);
var y = true;
console.log(x.equals(y)); // true
console.log(x == y); // true
console.log(x === y); // false
//console.log(y.equals(x)); => erreur

Etc.

Bref quand on compare des variables avec equals, == ou === en Rhino il faut bien savoir ce que l’on fait…

PS: on a ajouté dans le doc un § sur le subtilités des comparaisons en Rhino et, sur suggestion de @Francois on a ajouté une note pour dire que == est la seule bonne option s’agissant de contraintes exécutées à la fois coté serveur et coté client en 4.0. Cf. https://www.simplicite.io/resources/documentation/01-core/basic-code-examples.md

Oui c’est toujours compliqué
Là on parle de contrainte client, donc de javascript pur.

De façon générale, seuls == et != sont à utiliser pour comparer les string en rhino et/ou en js.

Sinon en font, Simplicité surcharge bien le prototype de String.prototype.equals
donc le code aurait du marcher sauf si le field n’est pas un String.
il faudrait nous donner les logs d’erreur du navigateur.