sp-dev-fx-webparts/samples/react-adaptivecards
Hugo Bernier 0e3a7d74ee
Merge pull request #3078 from petkir/petkir-revert-jszip-update
revert sp-build-web and sp-webpart-workbench to ori version
2022-11-07 10:24:16 -05:00
..
.devcontainer Added all 1.12.1 and 1.13 containers 2022-02-14 02:52:18 -05:00
assets Changed docs links to learn 2022-10-24 09:42:45 -04:00
config Updated to SPFx 1.12.1 2021-08-02 21:24:11 -04:00
release Updated sample.json 2021-08-26 00:19:34 -04:00
src Changed docs links to learn 2022-10-24 09:42:45 -04:00
teams Updated to SPFx 1.12.1 2021-08-02 21:24:11 -04:00
.gitignore Added all 1.12.1 and 1.13 containers 2022-02-14 02:52:18 -05:00
.yo-rc.json Updated to SPFx 1.12.1 2021-08-02 21:24:11 -04:00
README.md Changed docs links to learn 2022-10-24 09:42:45 -04:00
gulpfile.js Updated to SPFx 1.12.1 2021-08-02 21:24:11 -04:00
package-lock.json Bump xmldom and adaptive-expressions in /samples/react-adaptivecards 2022-11-02 15:47:05 +00:00
package.json Merge pull request #3078 from petkir/petkir-revert-jszip-update 2022-11-07 10:24:16 -05:00
tsconfig.json Updated to SPFx 1.12.1 2021-08-02 21:24:11 -04:00
tslint.json Updated to SPFx 1.12.1 2021-08-02 21:24:11 -04:00

README.md

Adaptive Cards Host

Summary

Adaptive Cards are platform-agnostic snippets of user interface, written in JSON, that apps and services can openly exchange.

You'll find Adaptive Cards in many Microsoft products such as Microsoft Bots Framework, Cortana Skills, Outlook Actionable Messages, Power Automate, Power Virtual Agents, Microsoft Teams, Windows Timeline, and so on.

This sample creates an Adaptive Cards Host web part that you can use to display Adaptive Cards in your SharePoint applications.

Adaptive Cards Host

Compatibility

SPFx 1.12.1 Node.js v14 | v12 | v10 Compatible with SharePoint Online Does not work with SharePoint 2019 Does not work with SharePoint 2016 (Feature Pack 2) Local Workbench Partially) Hosted Workbench Compatible Compatible with Remote Containers

Applies to

Prerequisites

There are no pre-requisites, but you'll probably want to have some Adaptive Cards samples ready to try out the web part.

Solution

Solution Author(s)
react-adaptivecards Hugo Bernier (Tahoe Ninjas, @bernier)
react-adaptivecards Paul Schaeflein (http://www.schaeflein.net, @paulschaeflein)

Version history

Version Date Comments
1.0.0 March 24, 2020 Initial release
2.0.0 April 06, 2020 Added data and template URLs
2.1.0 June 11, 2020 Fixed breaking changes introduced with Adaptive Card Templating in May update
2.2.0 August 25, 2020 Upgraded to SPFx 1.11
2.2.1 February 23, 2021 Fixed FluentUI dependencies introduced with newer versions of Adaptive Cards React.
2.3.0 August 2, 2021 Upgraded to SPFx 1.12.1

Minimal Path to Awesome

  • Clone this repository
  • From your command line, change to the folder for this sample (react-adaptivecards)
  • In the command line run:
    • npm install
    • gulp serve

This sample can also be opened with VS Code Remote Development. Visit https://aka.ms/spfx-devcontainer for further instructions.

Don't want to clone the entire repository? Try downloading this folder as a Zip file. Unzip the file, and continue with the command-line instructions.

Features

The sample also supports the following features and concepts:

Adaptive Cards

This web part supports all features of the Adaptive Cards schema, including the Preview Adaptive Card Templating features (see below).

The web part uses a brand new control called AdaptiveCard, which you can use to embed Adaptive Cards in your own solutions.

Web Part Sample

To use the web part, follow these simple steps:

  1. Insert the Adaptive Cards Host web part on your page
  2. When prompted to Configure Adaptive Card Host, click Configure to display the property pane.
  3. Select Template JSON code editor and paste your Adaptive Card template JSON. You can find template JSON samples on the Adaptive Cards samples and templates page. Alternatively, you can copy the following JSON:
{
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "type": "AdaptiveCard",
  "version": "1.0",
  "body": [
    {
      "type": "TextBlock",
      "text": "Create Adaptive Card web parts",
      "weight": "bolder",
      "size": "medium"
    },
    {
      "type": "ColumnSet",
      "columns": [
        {
          "type": "Column",
          "width": "auto",
          "items": [
            {
              "type": "Image",
              "url": "https://pbs.twimg.com/profile_images/1112818195797176322/jAUChJDM_400x400.jpg",
              "size": "small",
              "style": "person"
            }
          ]
        },
        {
          "type": "Column",
          "width": "stretch",
          "items": [
            {
              "type": "TextBlock",
              "text": "Hugo Bernier",
              "weight": "bolder",
              "wrap": true
            },
            {
              "type": "TextBlock",
              "spacing": "none",
              "text": "Created {{DATE(2020-03-24T06:08:39Z, SHORT)}}",
              "isSubtle": true,
              "wrap": true
            }
          ]
        }
      ]
    },
    {
      "type": "TextBlock",
      "text": "Now that we have a control to embed Adaptive Cards in SharePoint web parts, we need to create some cool web parts.",
      "wrap": true
    },
    {
      "type": "FactSet",
      "facts": [
        {
          "title": "Board:",
          "value": "Web Part Samples"
        },
        {
          "title": "List:",
          "value": "Backlog"
        },
        {
          "title": "Assigned to:",
          "value": "Hugo Bernier"
        },
        {
          "title": "Due date:",
          "value": "Not set"
        }
      ]
    }
  ],
  "actions": [
    {
      "type": "Action.ShowCard",
      "title": "Set due date",
      "card": {
        "type": "AdaptiveCard",
        "body": [
          {
            "type": "Input.Date",
            "id": "dueDate"
          }
        ],
        "actions": [
          {
            "type": "Action.Submit",
            "title": "OK"
          }
        ]
      }
    },
    {
      "type": "Action.ShowCard",
      "title": "Comment",
      "card": {
        "type": "AdaptiveCard",
        "body": [
          {
            "type": "Input.Text",
            "id": "comment",
            "isMultiline": true,
            "placeholder": "Enter your comment"
          }
        ],
        "actions": [
          {
            "type": "Action.Submit",
            "title": "OK"
          }
        ]
      }
    }
  ]
}

Adaptive Card Templating

Adaptive Card Templating is a new feature that allows you to separate your Adaptive Card data from its layout.

The web part allows you to Use Adaptive Card Templating features with a simple toggle.

Templating toggle

When you use Adaptive Card Templating, the web part will prompt you to enter two things:

  • Your Adaptive Card template JSON
  • Some data -- either as a JSON structure or by connecting to a SharePoint list or document library.

You Need Data!

When browsing the Adaptive Cards samples and templates page, you can enable Adaptive Card Templating by toggling the Use Adaptive Card Templating setting on the page.

To use an Adaptive Card Templating sample, copy the Template JSON to the web part's Template JSON, and the Data JSON to the Data JSON web part property.

When you import a template JSON with Adaptive Card templating syntax, the web part will remind you that you should turn on Use Adaptive Card Templating.

Templating Detection

Using Adaptive Card Templating, you can connect your Adaptive Card to live data from a SharePoint list or document library.

To do so, follow these steps:

  1. In your SharePoint list or document library, create a view and define the columns you want to display, as well as your filter, sort, and limit options. The Adaptive Card will use the same settings.
  2. Add the Adaptive Card Host web part to a SharePoint page.
  3. Edit the web part's property pane. We'll skip the Template JSON and go straight to the Adaptive Card Templating section.
  4. Turn on Use Adaptive Card Templating Turn on Use Adaptive Card Templating
  5. From the Data Source, select List
  6. From the Select a list drop-down, pick your list or document library.
  7. From the Select a view drop-down, pick the view you created in Step 1 Select library and view
  8. To create your template JSON, you'll need to know what data your web part will receive from your list or library. If you need help with finding out what your data looks like, the web part will log your data JSON to your browser's dev tools console when your page is in Edit mode. Just look for Data JSON on the Console tab and copy that JSON. Dev Tools Console
  9. Armed with your Data JSON, go to the Adaptive Card Designer and paste your Data JSON in the Sample Data Editor then select the Copy the structure of this data into the Data Structure toolbox button to load your sample data into the designer. Sample Data Editor
  10. Create your Adaptive Card template using the editor. For repeating rows of data, make sure to bind your Container or ColumnSet to the {$root} Data context. All repeating items within the container/column set should bind to the {$data} Data context. Make sure to use the Preview mode to test your template before continuing. Data context
  11. Copy your template JSON from the Card Payload Editor
  12. Back on your SharePoint page, paste your JSON in the web parts Template JSON

NOTE: In a future version of this web part, we'll embed an Adaptive Card editor to make this process easier.

For example, this is a very basic template JSON for a SharePoint Document Library**:

{
    "type": "AdaptiveCard",
    "body": [
        {
            "type": "ColumnSet",
            "columns": [
                {
                    "type": "Column",
                    "width": "50px",
                    "id": "I",
                    "items": [
                        {
                            "type": "TextBlock",
                            "text": "ID",
                            "weight": "Bolder"
                        }
                    ]
                },
                {
                    "type": "Column",
                    "width": "stretch",
                    "items": [
                        {
                            "type": "TextBlock",
                            "text": "File Name",
                            "weight": "Bolder"
                        }
                    ]
                },
                {
                    "type": "Column",
                    "width": "stretch",
                    "items": [
                        {
                            "type": "TextBlock",
                            "text": "Editor",
                            "weight": "Bolder"
                        }
                    ]
                },
                {
                    "type": "Column",
                    "width": "stretch",
                    "items": [
                        {
                            "type": "TextBlock",
                            "text": "Modified",
                            "weight": "Bolder"
                        }
                    ]
                }
            ]
        },
        {
            "type": "ColumnSet",
            "columns": [
                {
                    "type": "Column",
                    "width": "50px",
                    "items": [
                        {
                            "type": "TextBlock",
                            "text": "{ID}",
                            "$data": "{$data}"
                        }
                    ]
                },
                {
                    "type": "Column",
                    "width": "stretch",
                    "items": [
                        {
                            "type": "TextBlock",
                            "text": "{FileLeafRef}",
                            "$data": "{$data}"
                        }
                    ]
                },
                {
                    "type": "Column",
                    "width": "stretch",
                    "items": [
                        {
                            "type": "TextBlock",
                            "text": "{Editor[0].title}",
                            "$data": "{$data}"
                        }
                    ]
                },
                {
                    "type": "Column",
                    "width": "stretch",
                    "items": [
                        {
                            "type": "TextBlock",
                            "text": "{Modified}",
                            "$data": "{$data}"
                        }
                    ]
                }
            ],
            "$data": "{$root}"
        }
    ],
    "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
    "version": "1.0"
}

DISCLAIMER: The sample above focuses on simplicity to get you started. We'd recommend you explore list formatting before using Adaptive Cards to render your lists. However, if you find that list formatting does not meet your needs, try using Adaptive Cards.

Adaptive Card Actions

The Adaptive Card schema supports Actions, which allow you to create interactive Adaptive Cards.

The web part supports all Adaptive Card actions, including:

However, if you want to support Action.Submit in your own web part, we recommend you implement your own onExecuteAction event handler on your AdaptiveCard control. The sample will simply pop-up an alert instead of performing a submit.

Markdown Support

Adaptive Cards provide support for Markdown syntax, but they do not render the Markdown.

In our sample, we used Markdown-it to process any Markdown syntax in the rendered Adaptive Card before displaying it in the web part.

Fallback Support

Adaptive Cards provide a mechanism for handling unknown Adaptive Card elements called Fallback.

When the client doesn't support an Adaptive Card element, or the version specified, it will display text (or markdown) by specifying a fallbackText element.

The web part provides fallback handling.

Fallback Support -- Steve Holt!

Support for UI Fabric

The component that is responsible for rendering Adaptive Cards in every application is called the Adaptive Card Host. It is the responsibility of every Adaptive Card Host to render the cards so that they take on the appearance of the application where the Adaptive Card will be displayed.

The following is an example of how the same Adaptive Card renders differently in each Adaptive Card Host: Adaptive Card Host Rendering

When the web part renders Adaptive Cards in SharePoint, it injects UI Fabric styles to ensure that the rendered card blends in with other SharePoint content.

Support for UI Fabric

The web part also ensures that the Adaptive Cards resize according to the web part's dimensions and adapt to the site's theme.

Layouts and colors affect the rendering

Section Background Color Support

In addition to theme color support, the web part uses the method described at Supporting Section Background to adjust to changing section colors.

Changing the section background color changes the Adaptive Card background as well

Keep in mind that some Adaptive Cards may include images which may not render well on different background colors. Also, the Strong section color may cause action buttons to render the same color as the background, but this appears to be a limitation of themes in SharePoint rather than a limitation of Adaptive Cards.

SharePoint RenderListDataAsStream API

To retrieve your list data, we use PnPJS's RenderListDataAsStream method. RenderListDataAsStream is the same method SharePoint calls when rendering lists and document libraries.

The method allows us to pass the selected View's CAML query and retrieve all the relevant data we need in a single call -- including the values for lookup and managed metadata fields.

Dynamically Loading Property Pane Resources

Our web part uses the Property Field Code Editor from the @pnp/spfx-property-controls library.

However, as you load more controls in your web part's property pane, you may notice that your web part takes longer to load. That is because the bundle sizes tend to increase with each new library you include in your solution.

This web part uses loadPropertyResources to dynamically load some of its property pane controls when the property pane is shown, as described in the Microsoft documentation on Dynamic loading.

You can use loadPropertyResources in your web part to reduce the number of resources that are loaded when the web part renders, and only load resources when the property pane of your web part is shown.

Dependent Property Pane Controls

The web part sample conditionally hides and shows property pane controls depending on which settings you choose.

Dependent Property Pane Controls

CodeTour

This project contains a CodeTour that will walk you through the areas of interest. To use it, make sure you install CodeTour for Visual Studio Code. When you open the project, you'll be prompted to start the tour, but you can also find the Code Walk-through tour in the CodeTour pane.

For More Information

If you'd like to read more about the various concepts illustrated in this sample, please refer to the following links:

Video

Adaptive Cards Host SharePoint Framework web part

Help

We do not support samples, but this community is always willing to help, and we want to improve these samples. We use GitHub to track issues, which makes it easy for community members to volunteer their time and help resolve issues.

If you're having issues building the solution, please run spfx doctor from within the solution folder to diagnose incompatibility issues with your environment.

You can try looking at issues related to this sample to see if anybody else is having the same issues.

You can also try looking at discussions related to this sample and see what the community is saying.

If you encounter any issues while using this sample, create a new issue.

For questions regarding this sample, create a new question.

Finally, if you have an idea for improvement, make a suggestion.

Disclaimer

THIS CODE IS PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.