Data Entry With Adaptive Cards (part 2) 8859

Data Entry With Adaptive Cards (part 2)

Published

In this post, we'll look at how Adaptive Cards can be used to build data entry forms.

In the previous post, I showed how to create a Power Automate flow that builds an Adaptive Card with data entry fields needed for creating a new Raiser's Edge NXT event. In this post, we'll create another Power Automate flow that will be triggered when the user clicks the Save button.

So far, my Adaptive Card definition has a placeholder action representing the Save button, defined like this:
  "actions": [
    {
      "type": "Action.Execute",
      "title": "Save"
    }
  ]
As mentioned in the documentation, Action.Execute is not supported by the Adaptive Card Host SPA. What we want to use instead is Action.Webrequest (which is a custom action defined by Blackbaud). This type of action provides a way to define the URL of a service that will be called when the action is invoked - when the user clicks the Save button, the data entry payload will be sent in a message to the specified URL (which can implement the custom business logic, in this case adding an event record). Here again, I'll use Power Automate to implement the service that will be called when the button is clicked.

First, I'll create a new flow using the Trigger a flow from a SKY Add-in Adaptive Card action template - this will produce a flow with the following overview:
64d3b4ce93449d4d3cfc018438679499-huge-ov

Similar to the first flow we created that builds the Adaptive Card, this flow will be triggered by an incoming HTTP request. It'll perform the same validation, then build a response to send back to the caller (the Blackbaud UI). As with the first flow, we can remove the context property from the trigger schema since this will be triggered by an add-in on the Raiser's Edge NXT Home page (which provides no additional context values).

Additionally, we need to update the schema in the trigger to include the values that will be provided by the Adaptive Card framework. When the Save button is clicked, the data specified by the user will be sent in the request payload as part of a "data" element. Each field that contains an id in the card will be represented as a property in the data payload. In our case, the card definition has fields with id values of name, description, category, etc. and we need to ensure that those fields are defined in the schema body of the flow trigger so we can reference them downstream in the flow. The template produces some placeholder fields named field1, field2, and field3 in the schema. I'll update the schema to use the actual field identifiers from my card definition:
d5e1455af870e59ed3066136fc483940-huge-tr
As with the first flow, I'll provide my SKY application ID in the Validate user identity token action:
3c3e93e87783cf5ea30fb9c8ce1b5bbd-huge-va
After the validation step, I'll use the Create an event action from the Raiser's Edge NXT Events connector to create the new event record, referencing the fields defined in the flow trigger (which will come from the user):
fe443bc1b2c4edc87ccc93998caa2477-huge-cr
Finally, I'll use a Compose action to build a simple message to send back to the user:
1d44e1dd75f7803e75481151721fe6c5-huge-re
Now I can save the flow to get the URL that can be used to trigger it, and then update the Adaptive Card action definition in my first flow. I'll change the type to Action.Webrequest, and add a url property with the URL of my second flow (note that this URL doesn't need to be encoded):
"actions" [
  {
    "type": "Action.Webrequest",
    "title": "Save",
    "url": "https://prod-137.westus.logic.azure.com:443/workflows/15006c27c17b4eba97a6..."
  }
]

(note: be careful when using the Adaptive Card designer as it won't know anything about Action.Webrequest - in fact, if you aren't careful the designer will remove the action from your card definition!)

...and that's it! When the Save button is clicked, the second Power Automate flow will be triggered. The values provided by the user will be included with the request, and the flow will use them to create a new event record. The user will see a toast message indicating that the event was created:
46e852dd16d8abf30ee3ff3603720d07-huge-ev

To summarize, Adaptive Cards can be use to capture user input with rich and highly interactive controls. Card actions can be used to implement business logic that incorporates values provided by the user. In this example, I used Power Automate to build one flow that returns the Adaptive Card definition, and then another flow that is triggered when the Save action button is clicked.

I hope these posts give you some inspiration into the art of the possible using these low-code tools. We'd love to hear any feedback, and welcome any questions you may have!

Happy (no) coding!
News SKY Developer Announcements 01/31/2023 12:57am EST

Leave a Comment

1 Comments
Alex Wong Alex Wong Mar '23

Hi, can the Adaptive Card action be such that when the URL (flow) is called and provided data, the response of the flow is “added” to the Adaptive Card?

I'm trying to work on an Adaptive Card, where the card allow for searching by appeal or fund:

323c137eac742b93b91222a0270edf25-huge-im

after searching (calling another flow that does the search), the response from the searching flow is displayed as a table of result under the search form.

Alex Wong Alex Wong Mar '23

Thanks for confirming this. Loading all the Appeal and Fund into the Adaptive Card to begin with is a method that would work, but I think I'm not going to do that. There are thousands of appeals and funds and if I were to load this everytime, that's a lot of processing wasted.

I guess I can go back to using AIO tiles for now until there's better support for Adaptive Card.

Also - I see “typeahead” functionality within cards for Microsoft Teams, but I haven't explored this in detail so I'm not sure if it will work for you, but maybe something to look into for inspiration: Typeahead search in Adaptive Cards - Teams | Microsoft Learn

Good question Alex! Currently, I don't think this is possible. Cards are supposed to be “declarative” (wholly defined by the card definition), and the response from the webrequest action (the flow called when the search button is clicked) can't “update” the existing card.

I had always envisioned being able to return a new card that would “replace” the existing card - I've seen other host applications do this, but the Adaptive Card spec isn't very opinionated about this type of user interaction scenario. But that could be something Blackbaud implements as a feature enhancement to the Adaptive Card Host SPA (i.e., if the response from a webrequest action has a Content-Type header indicating that the body contains an adaptive card, then clear the original card and replace it with the new card).

Alternately, instead of using a “search” metaphor, the initial card could use dropdowns that are populated by the flow that builds the card - i.e., fetch all funds/appeals in the flow and build dropdowns similar to what I illustrate in this post:

Share: