Langage de modèle de cartes adaptatives

La création de modèles permet de séparer les données de la disposition dans votre carte adaptative. Le langage de modèle est la syntaxe utilisée pour créer un modèle.

Lisez la vue d’ensemble de la création de modèles de cartes adaptatives.

Important

Changements cassants dans la version RC (Release Candidate) de mai 2020

Nous avons travaillé dur à la publication des modèles et nous sommes dans la dernière ligne droite ! Nous avons dû apporter des modifications mineures avant de finaliser la version.

Changements cassants de mai 2020

  1. La syntaxe de liaison a changé et passe de {...} à ${...}.
    • Par exemple : "text": "Hello {name}" devient "text": "Hello ${name}"

Liaison de données

L’écriture d’un modèle est aussi simple que de remplacer le contenu « non statique » de votre carte par des « expressions de liaison ».

Charge utile de carte statique

{
   "type": "TextBlock",
   "text": "Matt"
}

Charge utile de modèle

{
   "type": "TextBlock",
   "text": "${firstName}"
}
  • Les expressions de liaison peuvent être placées à n’importe quel endroit où le contenu statique peut se trouver.
  • La syntaxe de liaison commence par ${ et se termine par }. Par exemple : ${myProperty}
  • Utilisez la notation par points pour accéder aux sous-objets d’une hiérarchie d’objets. Par exemple : ${myParent.myChild}
  • Grâce à une gestion appropriée des valeurs Null, vous n’obtiendrez pas d’exceptions si vous accédez à une propriété Null dans un graphique d’objet.
  • Utilisez la syntaxe d’indexeur pour récupérer des propriétés par clé ou les éléments d’un tableau. Par exemple : ${myArray[0]}

Ajout des données

Maintenant que vous disposez d’un modèle, vous devez lui ajouter des données pour le finaliser. Pour ce faire, vous avez deux options :

  1. Option A : Inline dans la charge utile du modèle. Vous pouvez fournir les données inline dans la charge utile du modèle AdaptiveCard. Pour ce faire, il vous suffit d’ajouter un attribut $data à l’objet racine AdaptiveCard.
  2. Option B : En tant qu’objet de données distinct. Avec cette option, vous fournissez deux objets distincts au SDK de création de modèles au moment de l’exécution : template et data. Il s’agit de l’approche la plus courante, car en général, vous créez un modèle, puis vous y ajoutez des données dynamiques ultérieurement.

Option A : Données inline

{
    "type": "AdaptiveCard",
    "$data": {
        "employee": {
            "name": "Matt",
            "manager": { "name": "Thomas" },
            "peers": [{
                "name": "Andrew" 
            }, { 
                "name": "Lei"
            }, { 
                "name": "Mary Anne"
            }, { 
                "name": "Adam"
            }]
        }
    },
    "body": [
        {
            "type": "TextBlock",
            "text": "Hi ${employee.name}! Here's a bit about your org..."
        },
        {
            "type": "TextBlock",
            "text": "Your manager is: ${employee.manager.name}"
        },
        {
            "type": "TextBlock",
            "text": "3 of your peers are: ${employee.peers[0].name}, ${employee.peers[1].name}, ${employee.peers[2].name}"
        }
    ]
}

Option B : Séparation du modèle des données

Une autre approche, d’ailleurs plus vraisemblable, consiste à créer un modèle de carte réutilisable sans y inclure de données. Vous pouvez stocker ce modèle en tant que fichier et l’ajouter au contrôle de code source.

EmployeeCardTemplate.json

{
    "type": "AdaptiveCard",
    "body": [
        {
            "type": "TextBlock",
            "text": "Hi ${employee.name}! Here's a bit about your org..."
        },
        {
            "type": "TextBlock",
            "text": "Your manager is: ${employee.manager.name}"
        },
        {
            "type": "TextBlock",
            "text": "3 of your peers are: ${employee.peers[0].name}, ${employee.peers[1].name}, ${employee.peers[2].name}"
        }
    ]
}

Ensuite, chargez-le et fournissez les données au moment de l’exécution à l’aide des kits SDK de création de modèles.

Exemple JavaScript

Cet exemple utilise le package adaptivecards-templating.

var template = new ACData.Template({ 
    // EmployeeCardTemplate goes here
});

// Specify data at runtime
var card = template.expand({
    $root: {
        "employee": {
            "name": "Matt",
            "manager": { "name": "Thomas" },
            "peers": [{
                "name": "Andrew" 
            }, { 
                "name": "Lei"
            }, { 
                "name": "Mary Anne"
            }, { 
                "name": "Adam"
            }]
        }
    }
});

// Now you have an AdaptiveCard ready to render!

Prise en charge du concepteur

Le concepteur de cartes adaptatives a été mis à jour pour prendre en charge la création de modèles.

Faites un essai sur : https://adaptivecards.io/designer

image

  • Éditeur d’exemples de données : spécifiez des exemples de données pour afficher la carte associée aux données en mode Aperçu. Ce volet contient un petit bouton qui permet de remplir la structure de données avec les données d’exemple existantes.
  • Mode Aperçu : appuyez sur le bouton de la barre d’outils pour basculer entre l’expérience de modification et l’expérience d’aperçu de l’exemple de données.
  • Ouvrir l’exemple : cliquez sur ce bouton pour ouvrir divers exemples de charge utile.

Liaison avancée

Étendues de liaison

Des mots clés réservés vous donnent accès à différentes étendues de liaison.

{
    "${<property>}": "Implicitly binds to `$data.<property>`",
    "$data": "The current data object",
    "$root": "The root data object. Useful when iterating to escape to parent object",
    "$index": "The current index when iterating"
}

Affectation d’un contexte de données à des éléments

Pour affecter un « contexte de données » à un élément, ajoutez un attribut $data à l’élément.

{
    "type": "Container",
    "$data": "${mySubObject}",
    "items": [
        {
            "type": "TextBlock",
            "text": "This TextBlock is now scoped directly to 'mySubObject': ${mySubObjectProperty}"
        },
        {
            "type": "TextBlock",
            "text": "To break-out and access the root data, use: ${$root}"
        }
    ]
}

Répétition d’éléments dans un tableau

  • Si la propriété $data d’un élément de carte adaptative est liée à un tableau, cet élément est répété pour chaque élément du tableau.
  • Toute expression de liaison (${myProperty}) utilisée dans les valeurs de propriété a pour étendue l’élément individuel dans le tableau.
  • En cas de liaison à un tableau de chaînes, utilisez ${$data} pour accéder à l’élément de chaîne individuel. Par exemple : "text": "${$data}"

Par exemple, le TextBlock ci-dessous est répété 3 fois car $data est un tableau. Notez que la propriété text est liée à la propriété name d’un objet individuel dans le tableau.

{
    "type": "Container",
    "items": [
        {
            "type": "TextBlock",
            "$data": [
                { "name": "Matt" }, 
                { "name": "David" }, 
                { "name": "Thomas" }
            ],
            "text": "${name}"
        }
    ]
}

Ce qui donne :

{
    "type": "Container",
    "items": [ 
        {
            "type": "TextBlock",
            "text": "Matt"
        },
        {
            "type": "TextBlock",
            "text": "David"
        }
        {
            "type": "TextBlock",
            "text": "Thomas"
        }
    ]
}

Fonctions intégrées

Aucun langage de création de modèles ne serait complet sans une suite de fonctions d’assistance. La création de modèles de cartes adaptatives s’appuie sur le langage AEL, qui est un standard ouvert permettant de déclarer des expressions pouvant être évaluées sur un grand nombre de plateformes différentes. Comme il s’agit d’un vrai sur-ensemble de « Logic Apps », vous pouvez utiliser une syntaxe similaire à celle de Power Automate, etc.

Il ne s’agit là que d’un petit échantillon des fonctions intégrées.

Consultez la liste complète des fonctions prédéfinies du langage AEL.

Évaluation conditionnelle

  • if(expression, valeur_true, valeur_false)

Exemple if

{
    "type": "TextBlock",
    "color": "${if(priceChange >= 0, 'good', 'attention')}"
}

Analyse du JSON

  • JSON (jsonString) - Analyser une chaîne JSON

Exemple json

Il s’agit d’une réponse Azure DevOps où la propriété message est une chaîne sérialisée au format JSON. Pour pouvoir accéder aux valeurs de la chaîne, nous devons utiliser la fonction json dans notre modèle.

Données

{
    "id": "1291525457129548",
    "status": 4,
    "author": "Matt Hidinger",
    "message": "{\"type\":\"Deployment\",\"buildId\":\"9542982\",\"releaseId\":\"129\",\"buildNumber\":\"20180504.3\",\"releaseName\":\"Release-104\",\"repoProvider\":\"GitHub\"}",
    "start_time": "2018-05-04T18:05:33.3087147Z",
    "end_time": "2018-05-04T18:05:33.3087147Z"
}

Utilisation

{
    "type": "TextBlock",
    "text": "${json(message).releaseName}"
}

Ce qui donne

{
    "type": "TextBlock",
    "text": "Release-104"
}

Fonctions personnalisées

Les fonctions personnalisées sont prises en charge via les API des SDK de création de modèles.

Disposition conditionnelle avec $when

Pour supprimer un élément entier si une condition est remplie, utilisez la propriété $when. Si $when prend la valeur false, l’utilisateur ne voit pas l’élément.

{
    "type": "AdaptiveCard",
    "$data": {
        "price": "35"
    },
    "body": [
        {
            "type": "TextBlock",
            "$when": "${price > 30}",
            "text": "This thing is pricy!",
            "color": "attention",
        },
         {
            "type": "TextBlock",
            "$when": "${price <= 30}",
            "text": "Dang, this thing is cheap!",
            "color": "good"
        }
    ]
}

Composition de modèles

À l’heure actuelle, il n’est pas possible de composer ensemble les « parties » d’un modèle. Toutefois, nous explorons différentes pistes et espérons vous en dire plus très bientôt. Vos idées sont les bienvenues !

Exemples

Parcourez la page d’exemples mise à jour pour explorer toutes sortes de nouvelles cartes basées sur des modèles.