Linguagem do Modelo de Cartões Adaptáveis
A modelagem habilita a separação de dados do layout em um Cartão Adaptável. A linguagem do modelo é a sintaxe usada para criar um modelo.
Importante
Alterações da falha na versão Release Candidate de maio de 2020
Temos trabalhado duro para lançar a modelagem e, por fim, estamos na reta final. Com a proximidade do lançamento, tivemos que fazer algumas pequenas alterações da falha.
Alterações da falha a partir de maio de 2020
- A sintaxe de associação foi alterada de
{...}
para${...}
- Por exemplo:
"text": "Hello {name}"
se torna"text": "Hello ${name}"
- Por exemplo:
Associação a dados
Escrever um modelo é tão simples quanto substituir o conteúdo "não estático" do cartão por "expressões de associação".
Conteúdo do cartão estático
{
"type": "TextBlock",
"text": "Matt"
}
Conteúdo do modelo
{
"type": "TextBlock",
"text": "${firstName}"
}
- As expressões de associação podem ser colocadas praticamente em qualquer lugar em que o conteúdo estático possa ser colocado
- A sintaxe de associação começa com
${
e termina com}
. Por exemplo,${myProperty}
- Use Dot-notation para acessar os subobjetos de uma hierarquia de objetos. Por exemplo,
${myParent.myChild}
- A manipulação normal de null garante que você não obterá exceções se acessar uma propriedade nula em um grafo de objetos
- Use a Sintaxe do indexador para recuperar propriedades por chave ou itens em uma matriz. Por exemplo,
${myArray[0]}
Fornecer os dados
Agora que você tem um modelo, é necessário fornecer os dados que o completam. Você tem duas opções para fazer isso:
- Opção A: embutidos dentro do conteúdo do modelo. Você pode fornecer os dados embutidos dentro do conteúdo do modelo
AdaptiveCard
. Para fazer isso, basta adicionar um atributo$data
ao objetoAdaptiveCard
raiz. - Opção B: como um objeto de dados separado. Com essa opção, você fornece dois objetos separados para o SDK de modelagem em runtime: o
template
e odata
. Essa é a abordagem mais comum, pois normalmente você cria um modelo e fornece dados dinâmicos mais tarde, quando desejar.
Opção A: dados embutidos
{
"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}"
}
]
}
Opção B: Separar o modelo dos dados
Como alternativa, é mais provável que você crie um modelo de cartão reutilizável sem incluir os dados. Esse modelo pode ser armazenado como um arquivo e adicionado ao controle do código-fonte.
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}"
}
]
}
Em seguida, carregue-o e forneça os dados em runtime usando os SDKs de modelagem.
Exemplo do JavaScript
Use o pacote 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!
Compatibilidade do Designer
O Designer de Cartão Adaptável foi atualizado para ser compatível com a modelagem.
Confira em: https://adaptivecards.io/designer
- Editor de Dados de Exemplo – especifique os dados de exemplo aqui para exibir o cartão vinculado a dados quando estiver no "modo de visualização". Há um pequeno botão nesse painel para popular a estrutura de dados com base nos dados de exemplo existentes.
- Modo de Visualização: pressione o botão de barra de ferramentas para alternar entre a experiência de edição e de visualização de dados de exemplo.
- Abrir Exemplo: clique neste botão para abrir vários conteúdos de exemplo.
Associação avançada
Escopos de associação
Há algumas palavras-chave reservadas para acessar vários escopos de associação.
{
"${<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"
}
Atribuir um contexto de dados a elementos
Para atribuir um "contexto de dados" a qualquer elemento, adicione um atributo $data
ao elemento.
{
"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}"
}
]
}
Repetir itens em uma matriz
- Se a propriedade
$data
de um elemento de Cartão Adaptável estiver associada a uma matriz, o próprio elemento será repetido em cada item na matriz. - Todas as expressões de associação (
${myProperty}
) usadas nos valores da propriedade terão um escopo de item individual na matriz. - Caso esteja associando uma propriedade a uma matriz de cadeias de caracteres, use
${$data}
para acessar o elemento de cadeia de caracteres individual. Por exemplo,"text": "${$data}"
Por exemplo, o TextBlock
abaixo será repetido três vezes, uma vez que $data
é uma matriz. Observe como a propriedade text
está associada à propriedade name
de um objeto individual dentro da matriz.
{
"type": "Container",
"items": [
{
"type": "TextBlock",
"$data": [
{ "name": "Matt" },
{ "name": "David" },
{ "name": "Thomas" }
],
"text": "${name}"
}
]
}
Resultando em:
{
"type": "Container",
"items": [
{
"type": "TextBlock",
"text": "Matt"
},
{
"type": "TextBlock",
"text": "David"
}
{
"type": "TextBlock",
"text": "Thomas"
}
]
}
Funções internas
Nenhuma linguagem de modelagem está completa sem um pacote avançado de funções auxiliares. A modelagem de Cartões Adaptáveis é criada com base na AEL (linguagem de expressão adaptável), que é um padrão aberto para declarar expressões que podem ser avaliadas em várias plataformas diferentes. Além disso, é um superconjunto adequado dos "Aplicativos Lógicos" para o uso de uma sintaxe parecida à do Power Automate etc.
Isso é apenas uma pequena amostragem das funções internas.
Confira a lista completa das Funções predefinidas da linguagem de expressão adaptável.
Avaliação condicional
- if(expression, trueValue, falseValue)
if
exemplo
{
"type": "TextBlock",
"color": "${if(priceChange >= 0, 'good', 'attention')}"
}
Como analisar JSON
- json(jsonString): analise uma cadeia de caracteres JSON
json
exemplo
Essa é uma resposta do Azure DevOps em que a propriedade message
é uma cadeia de caracteres serializada em JSON. Para acessar valores dentro da cadeia de caracteres, é preciso usar a função json
no modelo.
Dados
{
"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"
}
Uso
{
"type": "TextBlock",
"text": "${json(message).releaseName}"
}
Resultando em
{
"type": "TextBlock",
"text": "Release-104"
}
Funções personalizadas
Há suporte para funções personalizadas por meio de APIs nos SDKs de modelagem.
Layout condicional com $when
Para remover um elemento inteiro caso uma condição seja atendida, use a propriedade $when
. Se $when
for avaliada como false
, o elemento não será exibido ao usuário.
{
"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"
}
]
}
Compor modelos
Atualmente, não há como compor "partes" de modelo juntas. Mas estamos explorando opções que esperamos compartilhar mais em breve. Todas as opiniões são bem-vindas!
Exemplos
Navegue na página de exemplos atualizada para explorar todos os tipos de novos cartões modelo.