React single/multi-select autocomplete in SPFx

This article provides steps to implement single or multi-select autocomplete drop-down list in the SharePoint Framework (SPFx) webpart, generally React select is a flexible and beautiful Select Input control for ReactJS with multi-select, autocomplete, async and creatable support.

Create a new web part project

Open power shell and run following comment to create a new web part by running the Yeoman SharePoint Generator

yo @microsoft/sharepoint

When prompted:

Enter the webpart name as your solution name, and then select Enter.
Select Create a subfolder with solution name for where to place the files.
Select Y to allow the solution to be deployed to all sites immediately.
Select N on the question if solution contains unique permissions.
Select WebPart as the client-side component type to be created.

The next set of prompts ask for specific information about your web part:

Enter your web part name, and then select Enter.
Enter your web part description, and then select Enter.
Select React framework as the framework you would like to use, and then select Enter.

Start Visual Studio Code (or your favorite code editor) within the context of the newly created project folder.

cd .\web part name\
code .

Install the library and required dependencies

npm install @pnp/sp --save
npm install --save react-select

Import the library into your application, update constructor, and access the root sp object in render for PnPjs libraries.

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

Configure the custom properties

Create a new source code file under the src\webparts\<Webpart name>\components\ folder of the solution. Create the new file I<web part name>State.ts and use it to create a TypeScript Interface

export interface ISpfxReactSelectState {
  options: Ioption[];
  selectedvalue:Ioption;
  selectedvalues:Ioption[];
}

export interface Ioption
{
  value:string;
  label:string;
}

In addition, you need to update the render method of the client-side web part to create a properly configured instance of the React component for rendering. The following code shows the updated method definition.

  public render(): void {
    const element: React.ReactElement<ISpfxReactSelectProps> = React.createElement(
      SpfxReactSelect,
      {
        description: this.properties.description,
        context: this.context
      }
    );
    ReactDom.render(element, this.domElement);
  }

Update the tsx file under the components. First, add some import statements to import the types you defined earlier. Notice the import for I<web part name>Props and I<web part name>State. There are also some imports for the PnP components used to render the UI of the PnP React component and pnp sp imports.

import * as React from 'react';
import styles from './SpfxReactSelect.module.scss';
import { ISpfxReactSelectProps } from './ISpfxReactSelectProps';
import { ISpfxReactSelectState, Ioption } from './ISpfxReactSelectState';
import Select from 'react-select';
import { PrimaryButton, autobind } from 'office-ui-fabric-react';
import { IFieldInfo } from "@pnp/sp/fields/types";
import { sp } from "@pnp/sp";
import "@pnp/sp/fields";
import "@pnp/sp/webs";
import "@pnp/sp/lists";
import "@pnp/sp/items";

Replace this render function with the following code.

  public render(): React.ReactElement<ISpfxReactSelectProps> {
    return (
      <div className={styles.spfxReactSelect}>
        <label>Country</label>
        <Select
          className="basic-single"
          classNamePrefix="Select"
          isClearable={true}
          isSearchable={true}
          value={this.state.selectedvalue}
          options={this.state.options}
          onChange={(value) => this.setState({ selectedvalue: value })}
        />
        <br />
        <label>Countries</label>
        <Select
          className="basic-single"
          classNamePrefix="Select"
          isClearable={true}
          isSearchable={true}
          isMulti
          value={this.state.selectedvalues}
          options={this.state.options}
          onChange={(value) => this.setState({ selectedvalues: value })}
        />
        <br />
        <PrimaryButton text="Save" onClick={this._savevalues} />
      </div>
    );
  }

Update the React component type declaration and add a constructor, as shown in the following example.

export default class SpfxReactSelect extends React.Component<ISpfxReactSelectProps, ISpfxReactSelectState> {
  constructor(props: ISpfxReactSelectProps, state: ISpfxReactSelectState) {
    super(props);
    sp.setup({ spfxContext: this.props.context });
    this.state = ({ options: [], selectedvalue: null, selectedvalues: [] })
    this._getvalues();
  }

place the below code inside the react component code, these functions using PnPjs to get and set values into the SharePoint list


  private async _getvalues() {
    const field1: IFieldInfo = await sp.web.lists.getByTitle("Sales").fields.getByInternalNameOrTitle("Country")();
    let listofCountries: Ioption[] = [];
    field1["Choices"].forEach(function (Country, i) {
      listofCountries.push({ value: Country, label: Country });
    });
    const item: any = await sp.web.lists.getByTitle("Sales").items.getById(1).get();
    let selectedCountries: Ioption[] = [];
    item.Countries.forEach(function (selected, i) {
      selectedCountries.push({ value: selected, label: selected });
    });
    let selectedCountry: Ioption = { label: item.Country, value: item.Country };
    this.setState({ options: listofCountries, selectedvalue: selectedCountry, selectedvalues: selectedCountries })
  }
  @autobind
  private async _savevalues() {
    let res: string[] = [];
    this.state.selectedvalues.forEach(function (va, i) {
      res.push(va.value);
    });
    let list = sp.web.lists.getByTitle("Sales");
    const i = await list.items.getById(1).update({
      Country: this.state.selectedvalue.value,
      Countries: { results: res }
    });
  }

Deploy the solution

You’re now ready to build, bundle, package, and deploy the solution.

Run the gulp commands to verify that the solution builds correctly.

gulp build

Use the following command to bundle and package the solution.

gulp bundle --ship
gulp package-solution --ship

Browse to the app catalog of your target tenant and upload the solution package. You can find the solution package under the sharepoint/solution folder of your solution. It is the .sppkg file. After you upload the solution package in the app catalog. you can find and the web part anywhere across the tenant.

Sharing is caring!

If you have any questions, feel free to let me know in the comments section.
Happy coding!!!

Simple input form in the Microsoft Teams Bot

This article provides steps to build simple input form in the Microsoft Teams Bot, generally, adaptive card awesome user interface for collect data and display data in Microsoft Teams chat. This input form is just a type of cards you can create. we make adaptive cards for any scenario possible! 

Prerequisite

Run below PowerShell command in Run as Administrator mode and close them once installation done

npm install --global --production windows-build-tools
npm install -g yo
npm install -g generator-botbuilder

Create a new bot project

Run below Powershell comment for creating new bot project 

yo botbuilder

When prompted:

? What’s the name of your bot? Enter your project name
? What will your bot do? Enter your project description
? What programming language do you want to use? TypeScript
? Which template would you like to start with? Empty Bot – https://aka.ms/bot-template-empty
? Looking good. Shall I go ahead and create your new bot? Y

Start Visual Studio Code (or your favorite code editor) within the context of the newly created project folder.

cd .\bot project name\
code .

Test run

Run the following comment to start your bot project 

npm start

Run the ngrok to make hosted url, for testing you don’t have to host the application in Azure. ngrok will help us to bypass that step for your test run

check this URL for download and setup the ngrok, run the below comment in sperate PowerShell window after your ngrok configuration is done.

Run below comment once ngrok setup is done, this will provide the public https url like this, https://e69bc5ddf0d4.ngrok.io

cd .\directory of ngrok.exe\

./ngrok.exe http http://localhost:3978/ -host-header="localhost:3978"

Creating Bot Channel in Azure

In the Azure portal search Bot services or click this link. In this page click +Add and select option called “Bot Channels Registration” and click “Create”. In the bot channel creation form select based on your preference and “Messaging endpoint” should be your ngrok url in following format https://e69bc5ddf0d4.ngrok.io/api/messages. Once everything selected click create.
Once bot channel created, goto “Bot Services” page and select newly created bot channel then click settings then you can find the read-only value of “Microsoft APP ID” also you can find the manage link to create new client secret. this both “Microsoft APP ID” and “client secret” values are the security layer for access your bot. you have to configure both values in your project.  

goto “src\index.ts” file in your project and find the adapter const and replace the values like below code

// Create adapter.
// See https://aka.ms/about-bot-adapter to learn more about adapters.
const adapter = new BotFrameworkAdapter({
    appId: '6c87964d-6fbb-4a73-8b80-235fda23e625',
    appPassword: 'ABJXyqm22GH.h5685qDvCMUH_75.VR._n~'
});

One more step has to do in the Azure, go to your bot channel and click Channels and select Microsoft Teams and click done.

Adaptive Card

we can make the adaptive card designs at https://adaptivecards.io/

{
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "type": "AdaptiveCard",
  "version": "1.0",
  "body": [
    {
      "type": "TextBlock",
      "text": "Please enter your details"
    },
    {
      "type": "Input.Text",
      "id": "firstName",
      "placeholder": "What is your first name?"
    },
    {
      "type": "Input.Text",
      "id": "lastName",
      "placeholder": "What is your last name?"
    },
    {
      "type": "Input.Text",
      "id": "email",
      "placeholder": "What is your Email?"
    }

  ],
  "actions": [
    {
      "type": "Action.Submit",
      "title": "Submit",
      "data": {
        "x": 13
      }
    }
  ]
}

In the src\bot.ts file import the adaptive card and use it  

import { ActivityHandler,CardFactory } from 'botbuilder';
const card = require('../resources/InputFormCard.json');

export class EmptyBot extends ActivityHandler {
    constructor() {
        super();
        this.onMessage(async (context, next) => {
            if(context.activity.value)
            {
                await context.sendActivity(`Name: ${context.activity.value.firstName}\n\n\n\nMobile Number: ${context.activity.value.lastName}\n\n\n\nEmail: ${context.activity.value.email}`);;
            }
            await next();
        });

        this.onMembersAdded(async (context, next) => {
            const membersAdded = context.activity.membersAdded;
            for (const member of membersAdded) {
                if (member.id !== context.activity.recipient.id) {
                    const inputCard = CardFactory.adaptiveCard(card);
                    await context.sendActivity('Hello world!');
                    await context.sendActivity({ attachments: [inputCard] });
                }
            }
            await next();
        });
    }
}

Adding echo bot in Microsoft Teams

You have to add the “App Studio” if already not added. this app help to to make manifest file. This manifest file basically contains all the interaction details between your app and teams.
Open the “App Studio” app and select “Create a new app” and in the new app form, fill all the values in the details section then jump to the bots. in the bots section click setup and select existing bot and try to find your azure bot channel in the “Select from one of my existing bot” if it is disabled or not found then paste your app id in the “connect to different bot id text field. select all the scopes and click save. jump to the last “Test and distribute” tab install if you found error then download the zip file and got apps and choose “Upload a custom app” option. once app added select the app and click add to chat. Now your Echo chat is available to use in the teams chat section 

Bot Expolorer

Bot explorer is a very useful tool for bot functionality testing, you can download this app from this url, you also check the latest version before downloading from that link  

in the bot explorer click “Open Bot” button to see the open bot popup window, in this popup you have to enter the bot url, you can enter localhost url or ngrok url in this format https://e69bc5ddf0d4.ngrok.io/api/messages . Enter the Microsoft App ID and Microsoft App Password and click connect. even you can keep these both empty if your Microsoft App ID is not configured in your project

Sharing is caring!

If you have any questions, feel free to let me know in the comments section.
Happy coding!!!

Hello World Tab in Microsoft Teams using yo Teams

This article provides steps to build the Hello World Tab in Microsoft Teams using yo Teams,

The yo Teams generator allows you to simply create and scaffold projects that include one or more Microsoft Teams features such as:

  • Bots – based on Bot Framework
  • Messaging Extensions – actions and query
  • Tabs, with support for Single-Sign-On
  • Connectors
  • Outgoing Webhooks

This article, we going to create Tabs, with support for Single-Sign-On

Implementing a Single sign-on (SSO)

Have to create one new app in the Azure active directory, click below to navigate to the App registration page and click “New Registration”

https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/RegisteredApps

In the “Register as application” page give any name and select “Accounts in any organizational directory (Any Azure AD directory – Multitenant) and personal Microsoft accounts (e.g. Skype, Xbox)” and ignore the redirect URI as it is and click Register

Copy the newly created application ID from the Application overview page and keep it somewhere,

Prepare the ngrok URL

ngrok to can provide temporary public hosted URL, just for testing or development we don’t have to host the application in Azure or somewhere. ngrok will provide the public hosted url and the URL will target your localhost URL

check this URL for download and setup the ngrok, run the below comment in sperate PowerShell window after your ngrok setup is done. here setup means simple registration process from ngrok

./ngrok.exe http http://localhost:3007/ -host-header="localhost:3007"

That comment will provide the public https url like this, https://e69bc5ddf0d4.ngrok.io

Now go back to your azure, and select your newly created app then select “Expose an API”. In the top of the page, you can find the set option for Application ID URI, modify the uri in following format (api:// + ngrok url + applicationid) api://7074e3b7107f.ngrok.io/644707d7-5d3e-48f5-a408-bf0a953a8036

Click “+ Add new scope” button, fill values like below

Scope nameaccess_as_user
Who can consent?Admins and users
Admin consent display nameCan be enter anything
Admin consent descriptionCan be enter anything
User consent display nameCan be enter anything
User consent descriptionCan be enter anything
StateEnabled

add below two ids under “Add a client application” section, these are the team’s windows and mobile apps id, which is never changing. so we always have to use this same id. while you add don’t forgot to select the newly created scope

5e3ce6c0-2b1f-4285-8d4b-75ee78787346

1fec8e78-bce4-4aaf-ab1b-5451cc387264

Next, we have to provide permission for the Azure app, select “API Permission” and click “Add permission” > Graph API > Delegated permissions > select following and click “Add Permission” and click “Grand Admin consent”

☑ email – View users’ email address
☑ offline_access-Maintain access to data you have given it access to
☑ openid – Sign users in
☑ profile – View users’ basic profile

Prerequisite (Setup and prepare your machine)

Run below PowerShell command in Run as Administrator mode and close them once installation done

npm install --global --production windows-build-tools
npm install yo gulp-cli --global
npm install generator-teams --global

Create a new Teams project

Run below Powershell comment for creating new teams project

yo teams

When prompted:

select the values same as like this screenshot pass the ngrock url and azure AD application id

Build and Run your app

Run following PowerShell comments once the project is created for Build and Run the app

gulp manifest
gulp build
gulp serve

Now you can access the app in this url http://localhost:3007/<tabname>/ also can access via ngrok url

When you access inside the teams, the application can be access the graph API and it will show the current user name

Run your app in Microsoft Teams

Installation zip package can be found in the package folder, In the Microsoft teams application or also can teams access via browser. select Apps, click “Upload a custom app” and Upload the file in the Microsoft Teams. Once added app can be accessible in any teams.

Select any one the teams and select any channel and one the top click Plus icon, in the popup search your app and add and access

Sharing is caring!

If you have any questions, feel free to let me know in the comments section.
Happy coding!!!