Interpolation
L'interpolation est le mécanisme qui vous permet d'accéder aux données de vos objets Miel directement dans vos formules.
Qu'est-ce que l'interpolation ?
L'interpolation permet d'insérer dynamiquement des valeurs provenant de vos objets dans une formule. Un champ se nomme directement : objet.champ.
Par exemple, si vous avez un objet "Commande" avec un champ "total", vous pouvez y accéder ainsi :
commande.totalQuand la formule s'exécute, commande.total sera remplacé par la valeur réelle du champ (par exemple, 1500).
Pourquoi "interpolation" ?
Le terme vient de l'idée d'"intercaler" des valeurs dynamiques dans une expression. C'est un concept courant dans de nombreux langages de programmation et systèmes de templates.
Accès aux champs
La syntaxe de base pour accéder à un champ est typeObjet.nomChamp.
commande.total // Le total de la commande
client.nom // Le nom du client
produit.prixUnitaire // Le prix unitaire du produit
facture.dateEcheance // La date d'échéance de la factureContexte de la formule
Le type d'objet que vous pouvez utiliser dépend du contexte où la formule est définie. Par exemple :
- Dans une formule sur un objet "Commande", vous avez accès aux champs de la commande
- Si la commande a un lien vers un "Client", vous pouvez naviguer vers ses champs
- Si la commande contient des "Produits", vous pouvez accéder à leurs propriétés
Références spéciales
Outre les champs classiques, Miel propose plusieurs références spéciales pour des cas d'usage courants.
context.user — L'utilisateur connecté
Référence à l'utilisateur actuellement connecté. Utile pour personnaliser l'affichage ou filtrer des données.
// Afficher le nom de l'utilisateur connecté
selfUser.fullname
// Filtrer les tâches assignées à l'utilisateur actuel
projet.taches.filter(tache => tache.assigneA === context.user)l => … — L'élément courant, nommé
Dans les fonctions qui itèrent sur un tableau (comme filter ou map), vous nommez l'élément en cours de traitement : le mot écrit avant la flèche est à vous, et il n'existe que dans le corps de sa lambda.
// Filtrer les nombres supérieurs à 10
[5, 15, 8, 20].filter(x => x > 10) // [15, 20]
// Doubler chaque nombre
[1, 2, 3].map(x => x * 2) // [2, 4, 6]
// Accéder aux champs de l'élément courant
commande.produits.filter(x => x.stock > 0)Itérations imbriquées — chaque lambda voit les noms de celles qui l'entourent
Quand vous avez des itérations imbriquées, la lambda intérieure voit le paramètre de l'extérieure. Deux lambdas imbriquées ne peuvent pas porter le même nom : le langage le refuse, pour qu'on ne croie jamais nommer un élément en en nommant un autre.
// Exemple avec double itération
commande.produits.tva.unique().map(tva => commande.produits.filter(produit => produit.tva === tva).map(produit => produit.prixHT
).sum()
)Dans cet exemple, tva fait référence au taux de TVA de la boucle externe, et produit au produit de la boucle interne.
context.args[0] — Ce que l'export ou le rapport itère
Une formule n'itère pas toujours elle-même : un export PDF peut répéter une page pour chaque projet, un rapport peut scinder une ligne par valeur. La formule est alors évaluée une fois par élément, et cet élément-là ne vient pas de son texte — aucune lambda ne peut le nommer. Il s'écrit context.args[0].
// Dans un widget d'une page d'export qui itère les projets :
// les lignes de la note de frais qui portent le projet de la page
{expenseClaim.lines.filter(ligne => context.args[0].name === ligne.project.name)}
// Dans une altération d'une ligne de rapport scindée : la valeur du split
context.args[0].fullnameBon à savoir : l'indice se compte depuis le dehors, quelle que soit la profondeur des lambdas où vous l'écrivez — context.args[0]désigne la même chose partout dans la formule. Et context est un mot réservé : vous ne pouvez pas en faire un nom de variable ni de paramètre.
Attention : l'emplacement dit aussi de quoi cet élément est fait — une page d'export le tient de ce qu'elle itère —, et les champs que vous lisez derrière lui sont donc vérifiés à l'enregistrement. Une fonction de tableau appliquée à une valeur simple est refusée avec le nom de la fonction et le type reçu :context.args[0].montantTotal.sum() ne s'enregistre plus simontantTotal est un nombre — il n'y a rien à sommer. Écrivezcontext.args[0].montantTotal, ou sommez la liste qui le porte. De la même façon, un champ qui n'existe pas sur cet élément est refusé, avec la phrase des chemins ordinaires : « x » n'existe pas sur l'objet « y ». Quand l'emplacement ne sait pas dire de quoi l'élément est fait, rien n'est vérifié : c'est la valeur, à l'exécution, qui tranche.
Combiner avec des calculs
L'interpolation devient vraiment puissante quand vous la combinez avec des opérateurs et des fonctions.
// Calcul simple
produit.prixHT * 1.20 // Prix TTC
// Calcul avec plusieurs champs
produit.prixUnitaire * produit.quantite // Sous-total
// Concaténation de texte
"Bonjour ".concat(client.prenom, " !") // "Bonjour Constance !"
// Condition basée sur une valeur
commande.total > 1000
? "Livraison gratuite"
: "Frais de port : 5€"Astuce
Quand votre formule devient complexe, pensez à utiliser des variables pour la rendre plus lisible.
Prochaine étape
Maintenant que vous savez accéder à vos données, apprenez à les manipuler avec les opérateurs de calcul et de comparaison.