Petit article vite fait en complément des rendus de cellules :
Pour rappel mes rendus de cellules fonctionnent avec le prototype suivant :
static fn(rowData: any, field: string): string { }
rowData contient l’objet de la ligne du tableau, à savoir un objet potentiellement complexe, et field contient le champs à rendre.
Mais
Mais si on a un objet complexe et que l’on souhaite rendre une sous-valeur, par exemple rue de notre adresse ?
{ adresse: { rue: string numero: string ... } ... }
Si je fais rowData[‘rue’] on est d’accord que ça nous donnera une erreur d’index non-trouvé ?
Notation en point
Une notation en point c’est, dans notre exemple : 'adresse.rue'
, c’est à dire la description du chemin pour avoir notre contenu à partir de la racine de l’objet.
Mais si on fait rowData[‘adresse.rue’], ça restera une erreur d’index non-trouvé ! Pourquoi ? Parce que ! Il ne va pas décortiquer tout seul votre clef, ça serait trop facile…
À noter que PrimeFace le traite par défaut quand vous utilisez leur système, mais dès qu’on part en « fait maison », mode dynamique, extension des templates, etc. ben zou ça ne fonctionne plus tout seul et il n’y a pas de service appelable pour vous aider.
Donc on va le faire nous même.
Résoudre la notation en point
Visuellement c’est simple, je veux descendre d’un cran à chaque point, sur base de la clef courante. Donc une récursive à plat en quelque sorte. Sans chipoter voici ma solution :
static solveDotNotation<T>(rowData: any, field: string) : T | undefined { const keys = field.split('.') let err = false let obj = rowData for (let ki in keys) { const k = keys[ki] if (obj[k]) { // Continue to dig next key obj = obj[k] } else { err = true break } } return err ? undefined : obj as T }
On divise field sur le point pour avoir une liste de clefs (keys) puis on parcours la liste. On a une variable obj, tel un pointeur mobile, initialement positionné à la racine de rowData, qui va évoluer à chaque passage de la boucle pour devenir le sous-élément. Si on ne trouve pas une étape on sort le plus vite possible, sinon on continue de descendre dans le terrier du lapin blanc.
En cas d’erreur, ici le choix est fait de renvoyer undefined qui permet, dans mon cas, de pouvoir jouer avec la notation de chainage optionnel (?.) dont voici mon exemple dans le cadre de mon rendu de valeurs ontologiques.
static OntologyValues(rowData: any, field: string): string { return CellRenderer.solveDotNotation<OntologyValue[]>(rowData, field)?.map<string>(ov=> ov.value || ov.object).join("\n<br/>") || "" }