Cible aussi les éléments imbriqués dans refreshRuntimeData()

Même défaut que celui corrigé dans applyOpenRowBindings() (commit
précédent), mais dans le second endroit qui régénère l'écran après un
changement de donnée : refreshRuntimeData() ne pouvait régénérer que les
éléments de PREMIER NIVEAU (seuls eux ont un data-el-id sur leur wrapper
.playElement). Un Répéteur niché dans un conteneur — comme celui de cet
écran — n'est jamais du premier niveau : c'est donc son ANCÊTRE de
premier niveau qui portait le marqueur "repeaterItem" à l'intérieur et
se faisait régénérer en entier à sa place, potentiellement l'écran
complet (jauges, onglets compris) si l'écran n'a qu'un seul gros
conteneur racine. C'était la cause réelle du "rechargement" toujours
visible après le précédent correctif : celui-ci ne portait que sur
applyOpenRowBindings(), pas sur cette 2e régénération déclenchée par
"Modifier une donnée"/"Modifier une variable".

Fix : même principe que le commit précédent — cible chaque élément
marqué (repeaterItem/jaugeBar/visibilityGated) directement via son
data-element-id, à n'importe quel niveau d'imbrication, en ne gardant
que les plus "hauts" parmi les éléments marqués pour ne jamais régénérer
un même nœud deux fois.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
william
2026-08-26 12:51:57 +02:00
co-authored by Claude Sonnet 5
parent 20adfa4169
commit f4a7a7340e
+36 -5
View File
@@ -463,8 +463,6 @@
// tout autre élément cliquable) reste silencieusement inerte pour // tout autre élément cliquable) reste silencieusement inerte pour
// le reste de la partie, sans le moindre message d'erreur visible. // le reste de la partie, sans le moindre message d'erreur visible.
try { try {
screenData.elements.filter(function(e){ return !e.parent_id; }).forEach(function(el) {
if (!el.rendered_html) return;
// "repeaterItem" (liste de données), "jaugeBar" (2.1 — jauge liée // "repeaterItem" (liste de données), "jaugeBar" (2.1 — jauge liée
// à une donnée) et "visibilityGated" (condition de visibilité — // à une donnée) et "visibilityGated" (condition de visibilité —
// voir render_element_html.py) sont les types d'éléments dont le // voir render_element_html.py) sont les types d'éléments dont le
@@ -472,9 +470,42 @@
// d'une action "Modifier un élément" posée à la main dans le // d'une action "Modifier un élément" posée à la main dans le
// graphe — eux seuls doivent être régénérés après un changement // graphe — eux seuls doivent être régénérés après un changement
// de donnée ou de variable. // de donnée ou de variable.
if (el.rendered_html.indexOf('repeaterItem') === -1 && el.rendered_html.indexOf('jaugeBar') === -1 && el.rendered_html.indexOf('visibilityGated') === -1) return; //
const wrapper = screenDiv.querySelector('.playElement[data-el-id="' + el.id + '"] .playElementInner'); // On cible ces éléments à N'IMPORTE QUEL niveau d'imbrication
if (wrapper) wrapper.innerHTML = el.rendered_html; // (pas seulement le premier niveau de l'écran), via leur
// data-element-id — disponible sur chaque élément rendu, pas
// seulement les éléments de premier niveau. Avant ce correctif,
// un Répéteur niché dans un conteneur (comme ici) n'était JAMAIS
// du premier niveau, donc c'est son ANCÊTRE de premier niveau
// qui portait le marqueur (le Répéteur imbriqué à l'intérieur)
// et se retrouvait régénéré en entier à sa place — potentiellement
// l'écran entier (jauges, onglets... compris) s'il n'y avait
// qu'un seul gros conteneur racine. Comme pour
// applyOpenRowBindings(), on ne garde que les éléments marqués
// les plus "hauts" dans l'arbre, pour ne jamais régénérer un même
// nœud deux fois.
const byId = {};
screenData.elements.forEach(function(e){ byId[e.id] = e; });
function hasMarker(e) {
return !!(e.rendered_html && (e.rendered_html.indexOf('repeaterItem') !== -1 || e.rendered_html.indexOf('jaugeBar') !== -1 || e.rendered_html.indexOf('visibilityGated') !== -1));
}
function hasMarkedAncestor(e) {
let p = e.parent_id ? byId[e.parent_id] : null;
while (p) {
if (hasMarker(p)) return true;
p = p.parent_id ? byId[p.parent_id] : null;
}
return false;
}
screenData.elements.filter(function(e) {
return hasMarker(e) && !hasMarkedAncestor(e);
}).forEach(function(el) {
const target = screenDiv.querySelector('[data-element-id="' + el.id + '"]');
if (!target) return;
const container = document.createElement('div');
container.innerHTML = el.rendered_html;
const newNode = container.firstElementChild;
if (newNode) target.replaceWith(newNode);
}); });
applyOpenRowBindings(); applyOpenRowBindings();
} catch (err) { } catch (err) {