Data Entry With Adaptive Cards (part 1) 8858

Data Entry With Adaptive Cards (part 1)

Published 1

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

In my previous post, I showed a technique for building a table entry dropdown control in an Adaptive Card. In this post, I'll use the same technique and build an Adaptive Card that recreates the "Add new event" data entry form in Raiser's Edge NXT. This will demonstrate not only more use cases for Adaptive Cards within the SKY Add-in framework, but also how to implement a card with an action button that performs some business logic.

For reference, here's the "Add new event" form from Raiser's Edge NXT:
980e60be40a94ca1fdebb8fae2488aba-huge-ad

The form has a mixture of fields
  • Event name is a simple required text field (max length 50)
  • Description is a multi-line text field
  • Category is a dropdown of values from the Event Category code table
  • Start/end dates are date fields
  • Start/end times are time fields
The fields are arranged vertically, with start/end dates and times utilizing two columns. When the Save button is clicked, a new event is created in Raiser's Edge NXT with the values provided by the user.

I'm going to recreate this as a SKY Add-in tile on the Raiser's Edge NXT Home page (you could show this exact same card in a flyout or a modal) - here's the end result:
045dbb32fec55a3f80478fefd797e8bf-huge-ad
To recreate this experience as an Adaptive Card, I'll need two separate Power Automate flows (using Power Automate isn't a requirement here, it's just a convenient means to an end):
  1. A flow that builds the card definition (which includes the desired data entry fields, the layout, and a single card action representing the "Save" button)
  2. A flow that will be triggered when the Save button is clicked (this flow will receive the inputs from the user and perform whatever interesting business logic is needed, which in this case is adding a new event record in Raiser's Edge NXT)
As usual, I find it easiest to build things like this in an incremental fashion...start small, get one piece working, then move on to the next piece.

I'll follow the Adaptive Card add-in tutorial found in our documentation, and begin by creating a new Power Automate flow using the Create an Adaptive Card SKY Add-in template. Here's a high-level view of the flow that is produced by the template:
1f9f93b6fa6a496069e918fcf78bac38-huge-fl
The flow will be trigged by an incoming HTTP request - it'll perform some validation, build some JSON representing the Adaptive Card, and then return a response back to the caller. You can think of this flow as acting like a web service - it receives a request, does some work, and returns a response.

As mentioned, we plan to show this as a tile on the Home page - you can see from the documentation on the Development office home tile dashboard extension point, this is a top-level extension point with no additional context. So I'll remove the "context" element from the flow trigger schema (technically, you can leave this in and Power Automate won't complain, but no value will be provided when the flow is triggered so there's no need to have it in the schema):
265e2bea9884677d4d73df7d27fe3fb4-huge-fl
I'll then handle the validation step and paste in the ID of my SKY application (it's obscured here just to avoid any confusion, it's not a sensitive value):
01db29602545a532f9ced898b174e7f6-huge-va
Now, the real fun begins! I need to build the Adaptive Card JSON. To do this, I'll hop over to the designer page on the Adaptive Card website and use the WYSIWYG editor to drag and drop elements onto the design surface. You can create a new card and start from a blank definition, or you can use one of the samples as a starting point. I generally select Outlook Actionable Messages as the host application (even though we're designing a card for the Blackbaud host application) because it's a close-ish approximation.

Using the designer takes a bit of practice, but it's not too difficult and you can see the card definition I was able to create (I'll add the card definition JSON payload as an attachment to this post):
83cbb1797e0070c4495fbee8f79d4500-huge-de

I used an "Action.Execute" action for the Save button just to get something to start with - it won't function to start, but we'll come back to that later. Also, and importantly, note that all of my input fields have a value specified for the "id" property. These values will define the shape of the "data" payload that will be sent when the user clicks the Save button later on.

Once I was happy with the card definition, I clicked the Copy card payload button to copy the JSON, and pasted it into the Compose Adaptive Card JSON action in my flow:
6db813089178f4f1662999c9428ef0cb-huge-co
In order to build the values for the Event Category dropdown, I'll use the technique from my previous post to fetch the event categories and project them into an array of JSON objects representing the choices for the Category ChoiceSet in my card definition.

After validating the user identity token, I'll insert a step before my Compose action and use the Send an HTTP request action to call the GetEventCategories endpoint in the Raiser's Edge NXT Event SKY API:
e9df42a43a6b63954f53d4aba78dfe3a-huge-ge
I'll use Parse JSON to parse the response and describe the schema which I'll get by generating it from the sample response on the endpoint reference page:
dd6c7cdf393a10f3156f094f40fa35c6-huge-pa
I'll use Select to project that response into the shape I need for a ChoiceSet (note that this shape is different from the shape of code table endpoints in my previous blog post, it returns an array of objects not an array of strings). As with code tables, we can use the same value for both title and description properties because we only need the description when adding an event via the connector:
2b31a9f40c67e5c0b3f0b326727ecfc2-huge-se
Now I can update the Compose action that builds the card definition and make use of the output from the Select action when defining the choices for my ChoiceSet:
15e6ed4e743c0beb252be7a8578ca10b-huge-ch
My flow overview now looks like this:
042caf52e8e49ed8fdd35e56f4f622fb-huge-ne
I haven't created the second flow needed for this scenario yet - we'll tackle that in the next post. For now, I'll save this flow in order to get the URL that can be used to trigger the flow, and I'll use that URL when registering my SKY Add-in (and as mentioned in the documentation, don't forget to encode the URL before registering your add-in). This also allows me to test that my card definition is working before getting too far along.

In the developer portal, I'll create a new SKY Add-in and use the /tile route within the Adaptive Card Host SPA (since we'll be displaying this card as a tile on the Home page):
c6464438a3cecfd98770703927fae23b-huge-ad

Once my add-in is registered and my SKY application is connected to my Raiser's Edge NXT environment, I'll see the tile containing my Adaptive Card when I visit the Home page within Raiser's Edge NXT! The "Category" dropdown will contain the available values from the Event Categories code table and the date/time controls will function and have nice calendar and time-picker interactions!
045dbb32fec55a3f80478fefd797e8bf-huge-ad
The Save button doesn't function yet, but we'll implement that along with the second flow that will be triggered when the button is clicked in the next post, so stay tuned!
News SKY Developer Announcements 01/31/2023 12:57am EST

Leave a Comment

2 Comments
Sami Zoss Sami Zoss May '23

Dumb question, but how is this better then just adding an event in RENXT using the Events Module?

Hi Sami, the intent of this post is to illustrate how to use Adaptive Cards to build a compelling user interface including capturing user data with rich input controls. When coupled with Power Automate, you can achieve a rich user experience on the frontend and rich, high fidelity business logic on the backend. Using the Event add form was just the means to that end using a scenario that was fairly intuitive but complex enough to convey the art of the possible.

Dan Snyder Dan Snyder Jan '23

Thanks for sharing these guides @Ben Lambert. Really cool option and I look forward to seeing what everyone comes up with!

Share: