Champs formule : la référence circulaire

Une formule de champ peut lire les champs d'une fiche liée, même quand cette fiche appartient à la même table. Elle ne peut pas, en revanche, lire son propre champ sur cette fiche : l'éditeur de formules la refuse, avec le message « Circular reference ».

Le cas

Une table Groups porte une référence vers elle-même, Parent : un sous-groupe désigne ainsi son groupe. Le champ formule Members choisit les personnes d'un pays (Country filter), et un sous-groupe doit prendre les siennes parmi les membres de son groupe :

Ninox
let country := 'Country filter';
let candidates := if Parent then Parent.Members else select People end;
candidates[Country = country]

L'éditeur de formules refuse ce code : « Circular reference: Members ».

Pourquoi

Ninox raisonne par champ, pas par fiche. Pour compiler la formule de Members, il doit connaître le type de Parent.Members, donc compiler la formule de Members… celle-là même qu'il est en train de compiler. Peu importe que la fiche parente ne soit jamais la fiche elle-même : la dépendance est refusée dès la compilation.

Attention

La même expression ne provoque aucune erreur quand elle est évaluée par l'interface de programmation (/query), ni quand elle est placée dans la formule d'un autre champ. Seul l'éditeur de formules du champ qu'elle lit la refuse : un essai réussi ailleurs ne garantit donc pas qu'elle sera acceptée.

La solution : un second champ

Laissez Members calculer sa liste sans lire le groupe parent :

Ninox
let country := 'Country filter';
select People where Country = country

Puis confiez la restriction à un second champ formule, Effective members, qui lit Members sur la fiche et sur son parent :

Ninox
if Parent then
    let parentMembers := Parent.Members;
    Members[contains(parentMembers, this)]
else
    Members
end

Effective members lit Members, mais Members ne lit pas Effective members : il n'y a plus de cycle. Dans les crochets, this désigne la personne examinée ; c'est pourquoi les membres du parent sont lus avant, dans une variable.

À savoir

  • Le champ Members d'un sous-groupe contient désormais des personnes qui ne sont pas membres du groupe : tout ce qui affiche ou utilise les membres (vues, boutons, fonctions globales) doit lire Effective members.
  • Un cycle peut aussi passer par deux champs : Members qui lirait Parent.'Effective members' formerait la boucle Members → Effective members → Members. Nous n'avons pas vérifié comment Ninox traite ce cas : évitez-le de la même façon.