Save Data From Viva Connection Adaptive Card to SharePoint List
Blog

Save Data From Viva Connection Adaptive Card to SharePoint List using SPFx ACE – Part 1

By Priyanka Sen  |  Published on June 21, 2022

Save Data From Viva Connection Adaptive Card to SharePoint List using SPFx ACE

Introduction:

Adaptive card extension, also known as ACE, is a new feature of SPFx. An awesome adaptive card with a brilliant custom form in its quick view that saves data in a SharePoint list can easily be created using the SPFx adaptive card extension and PnP JS. In this first part of the 2-part blog series, we will see how to save data to the SharePoint list. After reading this blog, you will learn about-

  • How to create an SPFx Adaptive card extension of type Image Card.
  • How to display the current logged-in username on that card.
  • How to add a button to that card.
  • How to use state and props in ACE.
  • How to display a form with a text field, a dropdown, and a date field in the Quick view.
  • How to make the fields required and display error message if found blank on submit of the form.
  • How to save the form data in a SharePoint list.
  • And some bonus points at the end of the article.
Save Data From Viva Connection Adaptive Card to SharePoint List using SPFx ACE
So, let us begin. We will follow the following steps: –
  1. Create an SPFx Adaptive card extension project.
  2. Import packages.
  3. Create SharePoint service functions.
  4. Edit MyToDosAdaptiveCardExtension class
  5. Edit the card view.
  6. Edit the quick view to create a form.
  7. Create a SharePoint list to save data
  8. Implement the save and cancel functionalities

Prerequisite

This article assumes that the developer has-

  1. Node: 14.18.0
  2. SharePoint generator: 1.14.0

Create a SharePoint list to save data

Create a SharePoint list with the name- ‘ToDoList’ and add a Date column with internal name ‘TaskDate’ and a choice column with the internal name ‘TaskPriority’ with 3 choices- High, Medium, and low.

Save Data From Viva Connection Adaptive Card to SharePoint List using SPFx ACE

Create an SPFx Adaptive card extension project

Step 1: Create a new directory for the project and change the current folder to that directory.

Step 2: Create a new project by running the Yeoman SharePoint Generator from within the new directory created for the project using the following command:

yo @microsoft/sharepoint

Save Data From Viva Connection Adaptive Card to SharePoint List using SPFx ACE

Step 3: Select the following options-

  1. Type of client-side component: Adaptive Card Extension
  2. Template: Image Card Template
  3. Extension name: MyToDos
Save Data From Viva Connection Adaptive Card to SharePoint List using SPFx ACE

Now after the project is created, open it in VS Code. It will have the following structure

Save Data From Viva Connection Adaptive Card to SharePoint List using SPFx ACE

Open the serve.json file inside the config folder and update the initial page and set your site workbench page as the initial page as follows:

https://<demoTenant>.sharepoint.com/sites/<MyHome>/_layouts/workbench.aspx

Now you can run the application using the following command to see the initial look

gulp serve

Save Data From Viva Connection Adaptive Card to SharePoint List using SPFx ACE

Import Packages

Import the following required packages:

Save Data From Viva Connection Adaptive Card to SharePoint List using SPFx ACE

Create SharePoint Service functions

Create a folder called services and SPServices.ts file inside it so that it matches the following structure-

Save Data From Viva Connection Adaptive Card to SharePoint List using SPFx ACE

Add the following code inside the SPServices.ts file-

import { sp } from "@pnp/sp";
import "@pnp/sp/profiles";
import "@pnp/sp/webs";
import "@pnp/sp/lists";
import "@pnp/sp/items";
import "@pnp/sp/fields";

export const getUserProfileInfo = (): Promise<any> => {
    return sp.profiles.myProperties.get();
};

export const addItemToList = (listname: string, item: any): Promise<any> => {
    return sp.web.lists.getByTitle(listname).items.add(item);
};

export const getListFieldChoices = (listname: string,fieldname: string): Promise<any> => {
    return sp.web.lists.getByTitle(listname).fields.getByInternalNameOrTitle(fieldname).select('Choices,ID').get();
};

Edit MyToDosAdaptiveCardExtension class

Go to the MyToDosAdaptiveCardExtension.ts file. Add following import statements

import { sp } from "@pnp/sp";
import { getListFieldChoices, getUserProfileInfo } from './services/SPServices';

Add the following code below the import statements:

export interface IUserInfo {
  name: string;
  jobTitle: string;
  pictureUrl: string;
  email: string;
}

export interface IOption {
  title: string;
  value: string;
}

Update the state and props interfaces as follows:

export interface IMyToDosAdaptiveCardExtensionProps {
  title: string;
}

export interface IMyToDosAdaptiveCardExtensionState {
  userInfo:IUserInfo;  
  priorityOptions: IOption[];
}

Inside “onInit()” method write the following code before the return statement:

sp.setup({
      spfxContext: this.context
    });

    let userInfo: IUserInfo = {
      name: "",
      jobTitle: "",
      pictureUrl:"",
      email: "",
    };
    let priorityOptions: IOption[] = [];


    this.state = {
      userInfo,
      priorityOptions 
    };    

    getUserProfileInfo().then(resp=>{
      console.log("resp",resp);
      if(resp){
        userInfo.name = resp.DisplayName;
        userInfo.email = resp.Email;
        userInfo.jobTitle = resp.Title;
        userInfo.pictureUrl = resp.PictureUrl;
      }
      getListFieldChoices('ToDoList','Task Priority').then(choiceResp=>{
        console.log("choiceResp",choiceResp);
        if(choiceResp && choiceResp.Choices && choiceResp.Choices.length>0){
          priorityOptions = choiceResp.Choices.map(item=>{
            return {
              title: item,
              value: item
            };
          });
        }
      this.setState({
        userInfo,
        priorityOptions
       });
      }).catch(e=>console.log(e));
    }).catch(e=>console.log(e));

Edit the card view

Go to the CardView.ts and update the CardButton method as follows-:

public get cardButtons(): [ICardButton] | [ICardButton, ICardButton] | undefined {
    return [
      {
        title: "Add Todo",
        action: {
          type: 'QuickView',
          parameters: {
            view: QUICK_VIEW_REGISTRY_ID
          }
        }
      }     
    ];
  }

Update the data method as follows-:

public get data(): IImageCardParameters {
    return {
      primaryText: "Hi "+this.state.userInfo.name + ", get ready with your ToDos!",
      imageUrl: require('../assets/ToDo.png'),
      title: this.properties.title
    };
  }

Edit the quick view to create a form

Go to the QuickViewTemplate.json and replace the existing code with the following code

{
  "type": "AdaptiveCard",
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "version": "1.3",
  "body": [
      {
          "type": "TextBlock",
          "size": "Medium",
          "weight": "Bolder",
          "text": "${title}"
      },
      {
          "type": "ColumnSet",
          "columns": [
              {
                  "type": "Column",
                  "items": [
                      {
                          "type": "Image",
                          "style": "Person",
                          "url": "${userInfo.pictureUrl}",
                          "size": "Small"
                      }
                  ],
                  "width": "auto"
              },
              {
                  "type": "Column",
                  "items": [
                      {
                          "type": "TextBlock",
                          "weight": "Bolder",
                          "text": "${userInfo.name}",
                          "wrap": true
                      },
                      {
                          "type": "TextBlock",
                          "spacing": "None",
                          "text": "${userInfo.jobTitle}",
                          "isSubtle": true,
                          "wrap": true
                      }
                  ],
                  "width": "stretch"
              }
          ]
      },
      {
          "type": "Input.Text",
          "id": "todoDesc",
          "label": "Task Title:",
          "isRequired": true,
          "placeholder": "Please enter task title",
          "errorMessage": "This field in required"
      },
      {
        "type": "Input.ChoiceSet",
        "id": "taskPriority",
        "choices": "${priorityOptions}",
        "placeholder": "Select task priority",
        "label": "Task Priority",
        "value": "",
        "isRequired": true,
        "errorMessage": "Please select task priority"
    },
      {
        "type": "Input.Date",
        "id": "taskDate",
        "label": "Task Date",
        "isRequired": true,
        "errorMessage": "This field in required"
      }
  ],
  "actions": [
      {
          "type": "Action.Submit",
          "title": "Save",
          "style": "positive",
          "data": {
            "id": "btn_save"
          }
      },
      {
          "type": "Action.Submit",
          "title": "Cancel",
          "associatedInputs": "none",
          "style":"destructive",
          "data": {
            "id": "btn_cancel"
          }
      }
  ]
}

Implement the save and cancel functionalities

Go to the QuickView.ts file and add the following import statement

import { IUserInfo, IOption } from '../MyToDosAdaptiveCardExtension';
import { addItemToList } from '../services/SPServices';
import * as moment from 'moment-timezone';

Update the IQuickViewData interface as follows

  export interface IQuickViewData {
    userInfo: IUserInfo;
    priorityOptions: IOption[];
    title: string;
  }

Update the data() method as follows

  public get data(): IQuickViewData {
    const { userInfo, priorityOptions } = this.state;
    return {
      userInfo
      priorityOptions,
      title: this.properties.title
    };
  }

If run the project at this point, the card should look like below:

Save Data From Viva Connection Adaptive Card to SharePoint List using SPFx ACE

If we click the Add button, we can see the Quick view. And if we click the Save button without any input, the form will look as follows, even before implementing the Save functionality

Save Data From Viva Connection Adaptive Card to SharePoint List using SPFx ACE

Now let’s add the following code to add the Save functionality

public onAction(action: IActionArguments): void {
    console.log("action",action);
    const { id, todoDesc, taskPriority, taskDate } = action["data"];
        if (action["type"] === 'Submit') {
      if (id === 'btn_save') {
        let taskInfo = {
          Title:todoDesc,
          TaskPriority:taskPriority,
          TaskDate:moment(taskDate).format("MM/DD/YYYY hh:mm:ss A"),          
        };
        console.log(`taskInfo `,taskInfo);
        addItemToList('ToDoList',taskInfo).then(resp=>{
          console.log("resp ",resp);
          this.quickViewNavigator.close();
        }).catch(e=>{
          console.log("error ",e);
          this.quickViewNavigator.close();
        });
      } else if (id === 'btn_cancel') {
        this.quickViewNavigator.close();
      }
    }
  }

Now run the code and test by adding a task title and date. Then check the SharePoint list. You can see the data added to the list.

Save Data From Viva Connection Adaptive Card to SharePoint List using SPFx ACE

Bonus Points

  • Update the card image by adding any image in the Assets folder and updating the value of imageUrl key in the data() method in the CardView.ts file as follows-
imageUrl: require('../assets/ToDo.png'),
  • Update the icon in the card by adding the following method in the MyToDosAdaptiveCardExtension class-
protected get iconProperty(): string {
return require('./assets/ToDo3.png');
   }

Conclusion:

So far, we have learned to create an SPFx adaptive card extension that displays current users’ information and a form with some fields in the quick view to take user inputs. We have also learned how to save users’ inputs to a SharePoint list. Hope this article can help you to start with ACE. In Part 2 of this blog series, we will see how to display the list of items fetched from SharePoint list in Adaptive Card Quick View.

We hope you found this blog useful in understanding how to save data from the Viva connection adaptive card to SharePoint list using SPFx Adaptive Card Extension. Please reach out to us so that we can put our decades of Microsoft technologies experience and capabilities to work for your organization’s Digital Transformation

Leave a comment

Your email address will not be published. Required fields are marked *

Unravel The Complex
Stay Connected

Subscribe and receive the latest insights

Netwoven Inc. - Microsoft Solutions Partner

Get involved by tagging Netwoven experiences using our official hashtag #UnravelTheComplex