In the part 2 of Teams Approval using Power Automate, we will learn to how to implement approval
in Teams using Adaptive Cards. The part 1 of this series is here.
So, let’s start with little introduction of Adaptive Cards
Adaptive Cards are platform independent snippets of UI, written in JSON, that applications can openly exchange. When delivered to a specific app, the JSON is transformed into native UI that automatically adapts to its look and feel. It helps design and integrate light-weight UI for all major platforms and frameworks.
E.g. if you are using expense report adaptive card in Teams, Outlook and Bot Framework, then same adaptive card can be used across all the three apps and it will adapt the native UI of the parent application where it is being displayed.
Card Authors defines their card using the card designer (https://adaptivecards.io/designer/). As card author designs the card, JSON schema for the card is automatically created by the designer. Then card author takes the json schema of the card and uses it in application. Designer provides drag and drop experience to the author to design the card, so author does not require any understand of JSON schema.
Now we will learn to create a sample flow that implements the Teams Approval using Power Automate with Adaptive Cards
First you will need a SharePoint list to store the request data which will be processed by Flow. Below is the SharePoint List structure which I am using in the walkthrough:
Below is the example adaptive card that I have used for this sample. If you want to use similar sample then copy the json code given below, or design your own adaptive card using the adaptive card designer
Sample Adaptive Card JSON below. Please note that I am using Power Automate dynamic content in this JSON to get the details of the item like Title, Description, Created, Private team column data populated in the adaptive card. So if you want to use the same JSON as is, then you need to match the column names as per the list structure I provided above, or change the dynamic content references once you paste this json in the Power Automate action.
{ "type": "AdaptiveCard", "body": [ { "type": "Container", "style": "emphasis", "items": [ { "type": "ColumnSet", "columns": [ { "type": "Column", "items": [ { "type": "TextBlock", "size": "Large", "weight": "Bolder", "text": "**New Team Request**" } ], "width": "stretch" } , { "type": "Column", "items": [ { "type": "Image", "url": "https://adaptivecards.io/content/pending.png", "altText": "Pending", "height": "30px" } ], "width": "auto" } ] } ], "bleed": true } , { "type": "Container", "items": [ { "type": "ColumnSet", "columns": [ { "type": "Column", "items": [ { "type": "TextBlock", "size": "ExtraLarge", "text": "@{triggerOutputs()?['body/Title']}", "wrap": true } ], "width": "stretch" } , { "type": "Column", "items": [ { "type": "ActionSet", "actions": [ { "type": "Action.OpenUrl", "title": "View Item", "url": "@{triggerOutputs()?['body/{Link}']}" } ] } ], "width": "auto" } ] } , { "type": "FactSet", "spacing": "Large", "facts": [ { "title": "Submitted By", "value": "**@{triggerOutputs()?['body/Author/DisplayName']}** @{triggerOutputs()?['body/Author/Email']}" } , { "title": "Team Name", "value": "@{triggerOutputs()?['body/Title']}" } , { "title": "Submitted On", "value": "@{triggerOutputs()?['body/Created']}" } , { "title": "Description", "value": "@{triggerOutputs()?['body/Description']}" } , { "title": "Private Team?", "value": "@{triggerOutputs()?['body/PrivateTeam_x003f_']}" } ] } ] } , { "type": "Container", "items": [ { "type": "ActionSet", "actions": [ { "type": "Action.Submit", "title": "Approve", "style": "positive", "data": { "id": "_qkQW8dJlUeLVi7ZMEzYVw", "action": "approve" } } , { "type": "Action.ShowCard", "title": "Reject", "style": "destructive", "card": { "type": "AdaptiveCard", "body": [ { "type": "Input.Text", "id": "RejectCommentID", "placeholder": "Please specify an appropriate reason for rejection.", "isMultiline": true } ], "actions": [ { "type": "Action.Submit", "title": "Send", "data": { "id": "_qkQW8dJlUeLVi7ZMEzYVw", "action": "reject" } } ], "$schema": "http://adaptivecards.io/schemas/adaptive-card.json" } } ] } ] } ], "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", "version": "1.2", "fallbackText": "This card requires Adaptive Cards v1.2 support to be rendered properly." }
Note this is important step as this action name will be used in other actions.
Note: It is important to set “Yes” for Should update card, so that card gets updated to show the update message after approver user clicks on approve/reject buttons in adaptive card, otherwise the card will still keep showing the approve/reject buttons and other users won’t know that approver user has already provided his/her decision on the card.
“body(‘PostAdaptiveCardToTeamsChannelforApproval’)[‘submitActionId’]” expression (without quotes) and on right hand side provide “Approve” value or whatever your action value is defined in your adaptive card for the buttons.