CRUD operation in SharePoint Online list using the SPFx React JS framework

SharePoint Online: CRUD operations using SPFx ReactJS framework

One comment

 18,944 total views,  82 views today

In this tutorial, we will learn about how we can do the CRUD operations in the SharePoint Online list using the SPFx ReactJS framework.

Key-Highlights

  • Create the SharePoint project scaffolding
  • How to stop the gulp server (Terminate batch job) while running SPFx project?
  • Customize the code for SharePoint CRUD operation using the SPFx React JS framework
  • How to configure a property for the “List Name”?
  • Create a model for List Item to handle the CRUD operation
  • Steps to add new controls to web part
  • Create an item to SharePoint list event handler
  • Read an item from SharePoint list event handler
  • Update an item in SharePoint list event handler
  • Delete an item from SharePoint list event handler
  • Create, Read, Update, Read complete operation code in CrudReact.tsx file
  • Demo: Test the ReactCRUD web part from the SharePoint Online site

We will go through this tutorial step by step and at the end of this tutorial, we will be able to see the below SPFX CRUD operation web part which renders in the browser.

SharePoint Online CRUD operation using the SPFx React JS framework
SharePoint Online CRUD operation using the SPFx React JS framework

 

SharePoint crud operations using SPFx React JS framework

Step 1:  Create the SharePoint project scaffolding

  1. Open the node.js command prompt and go to your desired folder path where you want to create your project.

Note:

  • If you have installed node.js – you can use any of the commands prompts like windows command prompt, PowerShell or Node.js command prompt.

2. Create a new project folder in the defined location, using the below command or manually:

md CRUD_React

3. Then go to the newly created project folder using the below command:

cd CRUD_React

React JS SPFx project folder location will look like something below:

React JS SPFx project folder location
React JS SPFx project folder location

3. Run the Yeoman SharePoint Generator – to create the SharePoint project scaffolding.

yo @microsoft/sharepoint

After a few seconds, we will be asked to pass the parameters in a sequence, so in most of the parameters,  pass the default selection as-is:

  1. Accept the default CRUD_React as your solution name(you can give your own solution name), and then press the enter key.
  2. Select SharePoint Online only (latest), for Which baseline packages do you want to target for your component(s)? and press the enter key.
  3. Select Use the current folder for where do you want to place the files?
  4. Select N  for “Do you want to allow the tenant admin the choice of being able to deploy the solution to all sites immediately without
    running any feature deployment or adding apps in sites?”
  5. Select N for “Will the components in the solution require permissions to access web APIs that are unique and not shared with other components in the tenant?”
  6. Select WebPart for “Which type of client-side component to create?”

Notes:

We can create below three types of project in SharePoint Framework (SPFx):

  • WebPart
  • Extension
  • Library

Now in the subsequent prompts – it will ask the specific input about the web part.

1. What is your Web part name? CRUD_React - hit enter key
2. What is your Web part description? (CRUD_React description)-hit enter key
3. Which framework would you like to use? (Use arrow keys) - select React framework

Notes:

There are three types of frameworks available, such as:

  • No JavaScript framework
  • React
  • Knockout

For this demo example, I have selected the “React”

Finally, the yo @microsoft/sharepoint – SPFX web part project execution status will be like below:

Congratulations your solution is created message
Congratulations your solution is created message

Step 2: Verify the project scaffolding

Run the “gulp build” and “gulp serve” command to verify the SPFx project is scaffolded successfully.

SPFx Gulp Build – run the “gulp build” command to build the project.

Gulp build command to build the SPFx framework project
Gulp build command to build the SPFx framework project

Office SharePoint Workbench SPFx Runtime test – to test the SPFx project run the “gulp serve” command.

Gulp serve command to run the SPFx framework project
Gulp serve command to run the SPFx framework project

Verify the web part renders successfully in the browser.

Note:

  • If the web part renders successfully in the browser, we can ensure the basic SPFx projected has been scaffolded successfully.
SPFx Gulp Serve succcessful - office SharePoint Workbench SPFx Runtime test
SPFx Gulp Serve succcessful – office SharePoint Workbench SPFx Runtime test

How to stop the gulp server (Terminate batch job) while running SPFx project?

We need to press the Ctrl+C key together.

Terminate batch job in SPFx project while it is running
Terminate batch job in SPFx project while it is running

Then we will get the “Server stopped” message.

Key “Y” in Termnate batch job (Y/N)? confirmation question.

Step 3: Customize the code for SharePoint CRUD operation using the SPFx React JS framework

To open the SPFx code in visual studio editor, we need to type “code .” (code single space dot).

SPFx React JS Framework - open code in visual studio editor
SPFx React JS Framework – open code in visual studio editor

How to configure a property for the “List Name”?

Any SPFx solution by default has description project, I mean at run time from the right side panel, we can chnage the description, and the same desciption gets rendered in the web part pane. Similary, in this tutorial we will allow user to configure the “List Name” and on the confiugred list the CRUD operation will happen in the context of current site, in the particular list.

Now, lets learn how we can allow user to pass the dynamic list name throguht the web part property configuration.

Note:

  • In this approach the CRUD operation can be applied only on “Title” column as by default each list will have a “Title” column – if you want do CRUD operation for all sort of columns, then in that list all the columns should be created as a prerequisites before the CRUD operation and accordingly code need to be customized.

Step 1:

Open mystrings.d.ts from “\src\webparts\CrudReact\loc\” folder.

Add this line as shown below – ListNameFieldLabel:string;

Add List Name Property in mystring.d.ts file - SPFX React Project
Add List Name Property in “mystring.d.ts” file – SPFX React Project
declare interface ICrudReactWebPartStrings {

  PropertyPaneDescription: string;

  BasicGroupName: string;

  DescriptionFieldLabel: string;

  ListNameFieldLabel:string;

}

declare module 'CrudReactWebPartStrings' {

  const strings: ICrudReactWebPartStrings;

  export = strings;

}

Step 2

In en-us.js file, which is located under “\src\webparts\CrudReact \loc\” folder add the display name for listName property.

Add this line as shown below – “ListNameFieldLabel”: “List Name” 

Add List Name Property in en-us.js file - SPFX React Project
Add List Name Property in en-us.js file – SPFX React Project
define([], function() {

  return {

    "PropertyPaneDescription": "Description",

    "BasicGroupName": "Group Name",

    "DescriptionFieldLabel": "Description Field",

    "ListNameFieldLabel": "List Name"  

  }

});
Note:
  • The en-us.js file is a resource language file – in this example, it means for english languge, so, if we want that the web part should be displayed in other languange non-english lagnuage as well, then there should be langunage specific separate file.

 

Step 3

set the member name to listName, in the interface IReactCrudProps.ts which is located under the “\src\webparts\CrudReact\components\” path.

Set the member name to listName in ICrudReactProps.ts file
Set the member name to listName in ICrudReactProps.ts file
import { SPHttpClient } from '@microsoft/sp-http'; 

export interface ICrudReactProps

 {

   //description: string;

   listName: string;   

   spHttpClient: SPHttpClient;  

   siteUrl: string; 

  

}

Step 4

Open the main webpart file (CrudReatWebPart.ts) from this path “\src\webparts\CrudReact” folder and update the below-highligted lines:

Webpart main file (CrudReactWebPart.ts) in SPFx React project
Webpart main file (CrudReactWebPart.ts) in SPFx React project

Change the below bold lines of code.

import * as React from 'react';

import * as ReactDom from 'react-dom';

import { Version } from '@microsoft/sp-core-library';

import {

  IPropertyPaneConfiguration,

  PropertyPaneTextField

} from '@microsoft/sp-property-pane';

import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';

import * as strings from 'CrudReactWebPartStrings';

import CrudReact from './components/CrudReact';

import { ICrudReactProps } from './components/ICrudReactProps';

export interface ICrudReactWebPartProps 

{

  description: string;

  listName: string;

}

export default class CrudReactWebPart extends BaseClientSideWebPart <ICrudReactWebPartProps> {

  public render(): void {

    const element: React.ReactElement<ICrudReactProps> = React.createElement(

      CrudReact,

      {

        //description: this.properties.description

        listName: this.properties.listName,

        spHttpClient: this.context.spHttpClient,  

        siteUrl: this.context.pageContext.web.absoluteUrl 

      }

    );

    ReactDom.render(element, this.domElement);

  }

  protected onDispose(): void {

    ReactDom.unmountComponentAtNode(this.domElement);

  }

  protected get dataVersion(): Version {

    return Version.parse('1.0');

  }

  protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {

    return {

      pages: [

        {

          header: {

            description: strings.PropertyPaneDescription

            //description: strings.ListNameFieldLabel

          },

          groups: [

            {

              groupName: strings.BasicGroupName,

              groupFields: [                

                  PropertyPaneTextField('listName', {

                  //label: strings.DescriptionFieldLabel

                  label: strings.ListNameFieldLabel

                })

              ]

            }

          ]

        }

      ]

    };

  }

}

Step 5

The UI in React framework gets served from the component CrudReact.tsx which is located at “\src\webparts\CrudReact\components\ReactCrud.tsx”. Make the changes for listName property in the component.

The UI in React gets served from component ReactCrud.tsx file
The UI in React gets served from component ReactCrud.tsx file
public render(): React.ReactElement<ICrudReactProps>{  

    const items: JSX.Element[] = this.state.items.map((item: IListItem, i: number): JSX.Element => {  

      return (  

        <li>{item.Title} ({item.Id}) </li>  

      );  

    });  

  

    return (  

      <div className={ styles.crudReact }>  

        <div className={ styles.container }>  

          <div className={ styles.row }>  

            <div className={ styles.column }>  

              <span className={ styles.title }>Welcome to SharePoint CRUD operation using React JS framework!</span>  

              <p className={ styles.subTitle }>Customize SharePoint experiences using Web Parts.</p>  

              <p className={ styles.description }>{escape(this.props.listName)}</p>  

                

              <div className={`ms-Grid-row ms-fontColor-white ${styles.row}`}>  

                <div className='ms-Grid-col ms-u-lg10 ms-u-xl8 ms-u-xlPush2 ms-u-lgPush1'>  

                  <a href="#" className={`${styles.button}`} onClick={() => this.createItem()}>  

                    <span className={styles.label}>Create an item</span>  

                  </a>   

                  <a href="#" className={`${styles.button}`} onClick={() => this.readItem()}>  

                    <span className={styles.label}>Read an item</span>  

                  </a>  

                </div>  

              </div>  

  

              <div className={`ms-Grid-row ms-bgColor-themeDark ms-fontColor-white ${styles.row}`}>  

                <div className='ms-Grid-col ms-u-lg10 ms-u-xl8 ms-u-xlPush2 ms-u-lgPush1'>  

                  <a href="#" className={`${styles.button}`} onClick={() => this.updateItem()}>  

                    <span className={styles.label}>Update an item</span>  

                  </a>   

                  <a href="#" className={`${styles.button}`} onClick={() => this.deleteItem()}>  

                    <span className={styles.label}>Delete an item</span>  

                  </a>  

                </div>  

              </div>  

  

              <div className={`ms-Grid-row ms-bgColor-themeDark ms-fontColor-white ${styles.row}`}>  

                <div className='ms-Grid-col ms-u-lg10 ms-u-xl8 ms-u-xlPush2 ms-u-lgPush1'>  

                  {this.state.status}  

                  <ul>  

                    {items}  

                  </ul>  

                </div>  

              </div>  

  

            </div>  

          </div>  

        </div>  

      </div>  

    );  

  }

Create a model for List Item to handle the CRUD operation

We need to create a model for list item to handle the CRUD operation.

Step 1

Add a class  IListItem.ts file for SharePoint List Item model.

IListItem.ts file for SharePoint List Item model
IListItem.ts file for SharePoint List Item model
export interface IListItem

{  

    Title?: string;  

    Id: number;  

}
Note:
  • In the above code, we have just added the Title, and ID column, as in this tutorial  we will be dealing only with the Title, and ID columns, if we want to deal with more columns, here thos columns structure should be created.

Step 2

As we know that React JS acts on the state change. So, we need to add a state into our solution.

IReactCRUDState.ts file to handle the state in SPFx React Project
IReactCRUDState.ts file to handle the state in SPFx React Project
import { IListItem } from './IListItem';  

  

export interface IReactCRUDState {  

  status: string;  

  items: IListItem[];  

}

Step 3

Configure the CrudReact.tsx for the above state.

Configure CrudReact.tsx file to handle the React state in SPFX project
Configure CrudReact.tsx file to handle the React state in SPFX project
import * as React from 'react';

import styles from './CrudReact.module.scss';

import { ICrudReactProps } from './ICrudReactProps';

import { IReactCRUDState } from './IReactCRUDState';

import { escape } from '@microsoft/sp-lodash-subset';

import { IListItem } from './IListItem';  

import { SPHttpClient, SPHttpClientResponse } from '@microsoft/sp-http';  

export default class CrudReact extends React.Component<ICrudReactProps, IReactCRUDState> {

  constructor(props: ICrudReactProps, state: IReactCRUDState) {  

    super(props);  

  

    this.state = {  

      status: 'Ready',  

      items: []  

    };  

  }  

  public render(): React.ReactElement<ICrudReactProps> 

  {

    return (

      <div className={ styles.crudReact }>

        <div className={ styles.container }>

          <div className={ styles.row }>

            <div className={ styles.column }>

              <span className={ styles.title }>Welcome to SharePoint!</span>

              <p className={ styles.subTitle }>Customize SharePoint experiences using Web Parts.</p>

              <p className={ styles.description }>{escape(this.props.listName)}</p>

              <a href="https://aka.ms/spfx" className={ styles.button }>

                <span className={ styles.label }>Learn more</span>

              </a>

            </div>

          </div>

        </div>

      </div>

    );

  }

Steps to add new controls to web part

Step 1

Open CrudReact.tsx from the \src\webparts\CrudReact\components\CrudReact.tsx path.

Step 2

Modify the Render method to display the below set of new buttons in SPFx:

  1. Create an item,
  2. Read an item,
  3. Update an item, and
  4. Delete an item
Modify the Render method to display the new button in SPFx
Modify the Render method to display the new button in SPFx

 

 

Step 3: Configure Site URL and spHttpClient property in ICrudReactProps.ts file We need to update the ICrudReactProps.ts interface which is located at “\src\webparts\CrudReact\components\” to include the siteURL and spHttpClient.

Configure Site URL and spHttpClient property in ICrudReactProps.ts file
Configure Site URL and spHttpClient property in ICrudReactProps.ts file

Note:

 

        • The read, update and delete operations will be performed on the latest item, so we dont need to pass anything to do read, update and delete operations, by default it will consider the latest item from the configured list.

       

       

 

 

Create an item to SharePoint list event handler:

Below is the create an item to SharePoint online list event handler code.

private createItem(): void {  

    this.setState({  

      status: 'Creating item...',  

      items: []  

    });  

    

    const body: string = JSON.stringify({  

      'Title': `Test item created by SPFx ReactJS on: ${new Date()}`  

    });  

    

    this.props.spHttpClient.post(`${this.props.siteUrl}/_api/web/lists/getbytitle('${this.props.listName}')/items`,  

    SPHttpClient.configurations.v1,  

    {  

      headers: {  

        'Accept': 'application/json;odata=nometadata',  

        'Content-type': 'application/json;odata=nometadata',  

        'odata-version': ''  

      },  

      body: body  

    })  

    .then((response: SPHttpClientResponse): Promise<IListItem> => {  

      return response.json();  

    })  

    .then((item: IListItem): void => {  

      this.setState({  

        status: `Item '${item.Title}' (ID: ${item.Id}) successfully created`,  

        items: []  

      });  

    }, (error: any): void => {  

      this.setState({  

        status: 'Error while creating the item: ' + error,  

        items: []  

      });  

    });  

  }

Read an item from SharePoint list event handler:

Below is the read an item from SharePoint online list event handler code.

private readItem(): void {  

    this.setState({  

      status: 'Loading latest items...',  

      items: []  

    });  

    

    this.getLatestItemId()  

      .then((itemId: number): Promise<SPHttpClientResponse> => {  

        if (itemId === -1) {  

          throw new Error('No items found in the list');  

        }  

    

        this.setState({  

          status: `Loading information about item ID: ${itemId}...`,  

          items: []  

        });  

        return this.props.spHttpClient.get(`${this.props.siteUrl}/_api/web/lists/getbytitle('${this.props.listName}')/items(${itemId})?$select=Title,Id`,  

          SPHttpClient.configurations.v1,  

          {  

            headers: {  

              'Accept': 'application/json;odata=nometadata',  

              'odata-version': ''  

            }  

          });  

      })  

      .then((response: SPHttpClientResponse): Promise<IListItem> => {  

        return response.json();  

      })  

      .then((item: IListItem): void => {  

        this.setState({  

          status: `Item ID: ${item.Id}, Title: ${item.Title}`,  

          items: []  

        });  

      }, (error: any): void => {  

        this.setState({  

          status: 'Loading latest item failed with error: ' + error,  

          items: []  

        });  

      });  

  }

Update an item in SharePoint list event handler:

Below is the update an item in SharePoint online list event handler code.

private updateItem(): void {  

    this.setState({  

      status: 'Loading latest items...',  

      items: []  

    });  

    

    let latestItemId: number = undefined;  

    

    this.getLatestItemId()  

      .then((itemId: number): Promise<SPHttpClientResponse> => {  

        if (itemId === -1) {  

          throw new Error('No items found in the list');  

        }  

    

        latestItemId = itemId;  

        this.setState({  

          status: `Loading information about item ID: ${latestItemId}...`,  

          items: []  

        });  

          

        return this.props.spHttpClient.get(`${this.props.siteUrl}/_api/web/lists/getbytitle('${this.props.listName}')/items(${latestItemId})?$select=Title,Id`,  

          SPHttpClient.configurations.v1,  

          {  

            headers: {  

              'Accept': 'application/json;odata=nometadata',  

              'odata-version': ''  

            }  

          });  

      })  

      .then((response: SPHttpClientResponse): Promise<IListItem> => {  

        return response.json();  

      })  

      .then((item: IListItem): void => {  

        this.setState({  

          status: 'Loading latest items...',  

          items: []  

        });  

    

        const body: string = JSON.stringify({  

          'Title': `Updated Item ${new Date()}`  

        });  

    

        this.props.spHttpClient.post(`${this.props.siteUrl}/_api/web/lists/getbytitle('${this.props.listName}')/items(${item.Id})`,  

          SPHttpClient.configurations.v1,  

          {  

            headers: {  

              'Accept': 'application/json;odata=nometadata',  

              'Content-type': 'application/json;odata=nometadata',  

              'odata-version': '',  

              'IF-MATCH': '*',  

              'X-HTTP-Method': 'MERGE'  

            },  

            body: body  

          })  

          .then((response: SPHttpClientResponse): void => {  

            this.setState({  

              status: `Item with ID: ${latestItemId} successfully updated`,  

              items: []  

            });  

          }, (error: any): void => {  

            this.setState({  

              status: `Error updating item: ${error}`,  

              items: []  

            });  

          });  

      });  

  }

Delete an item from SharePoint list event handler:

Below is the delete an item from SharePoint online list event handler code.

private deleteItem(): void

   {  

    if (!window.confirm('Are you sure you want to delete the latest item?'))

     {  

      return;  

     }  

    

    this.setState({  

      status: 'Loading latest items...',  

      items: []  

    });  

    

    let latestItemId: number = undefined;  

    let etag: string = undefined;  

    this.getLatestItemId()  

      .then((itemId: number): Promise<SPHttpClientResponse> => {  

        if (itemId === -1) {  

          throw new Error('No items found in the list');  

        }  

    

        latestItemId = itemId;  

        this.setState({  

          status: `Loading information about item ID: ${latestItemId}...`,  

          items: []  

        });  

    

        return this.props.spHttpClient.get(`${this.props.siteUrl}/_api/web/lists/getbytitle('${this.props.listName}')/items(${latestItemId})?$select=Id`,  

          SPHttpClient.configurations.v1,  

          {  

            headers: {  

              'Accept': 'application/json;odata=nometadata',  

              'odata-version': ''  

            }  

          });  

      })  

      .then((response: SPHttpClientResponse): Promise<IListItem> => {  

        etag = response.headers.get('ETag');  

        return response.json();  

      })  

      .then((item: IListItem): Promise<SPHttpClientResponse> => {  

        this.setState({  

          status: `Deleting item with ID: ${latestItemId}...`,  

          items: []  

        });  

    

        return this.props.spHttpClient.post(`${this.props.siteUrl}/_api/web/lists/getbytitle('${this.props.listName}')/items(${item.Id})`,  

          SPHttpClient.configurations.v1,  

          {  

            headers: {  

              'Accept': 'application/json;odata=nometadata',  

              'Content-type': 'application/json;odata=verbose',  

              'odata-version': '',  

              'IF-MATCH': etag,  

              'X-HTTP-Method': 'DELETE'  

            }  

          });  

      })  

      .then((response: SPHttpClientResponse): void => {  

        this.setState({  

          status: `Item with ID: ${latestItemId} successfully deleted`,  

          items: []  

        });  

      }, (error: any): void => {  

        this.setState({  

          status: `Error deleting item: ${error}`,  

          items: []  

        });  

      });  

  }

Create, Read, Update, Read complete operation code in CrudReact.tsx file

import * as React from 'react';
import styles from './CrudReact.module.scss';
import { ICrudReactProps } from './ICrudReactProps';
import { IReactCRUDState } from './IReactCRUDState';
import { escape } from '@microsoft/sp-lodash-subset';
import { IListItem } from './IListItem';  
import { SPHttpClient, SPHttpClientResponse } from '@microsoft/sp-http';  


export default class CrudReact extends React.Component<ICrudReactProps, IReactCRUDState> {


  constructor(props: ICrudReactProps, state: IReactCRUDState) {  
    super(props);  
  
    this.state = {  
      status: 'Ready',  
      items: []  
    };  
  }  
 

  public render(): React.ReactElement<ICrudReactProps>{  
    const items: JSX.Element[] = this.state.items.map((item: IListItem, i: number): JSX.Element => {  
      return (  
        <li>{item.Title} ({item.Id}) </li>  
      );  
    });  
  
    return (  
      <div className={ styles.crudReact }>  
        <div className={ styles.container }>  
          <div className={ styles.row }>  
            <div className={ styles.column }>  
              <span className={ styles.title }>Welcome to SharePoint CRUD operation using React JS framework!</span>  
              <p className={ styles.subTitle }>Customize SharePoint experiences using Web Parts.</p>  
              <p className={ styles.description }>{escape(this.props.listName)}</p>  
                
              <div className={`ms-Grid-row ms-fontColor-white ${styles.row}`}>  
                <div className='ms-Grid-col ms-u-lg10 ms-u-xl8 ms-u-xlPush2 ms-u-lgPush1'>  
                  <a href="#" className={`${styles.button}`} onClick={() => this.createItem()}>  
                    <span className={styles.label}>Create an item</span>  
                  </a>   
                  <a href="#" className={`${styles.button}`} onClick={() => this.readItem()}>  
                    <span className={styles.label}>Read an item</span>  
                  </a>  
                </div>  
              </div>  
  
              <div className={`ms-Grid-row ms-bgColor-themeDark ms-fontColor-white ${styles.row}`}>  
                <div className='ms-Grid-col ms-u-lg10 ms-u-xl8 ms-u-xlPush2 ms-u-lgPush1'>  
                  <a href="#" className={`${styles.button}`} onClick={() => this.updateItem()}>  
                    <span className={styles.label}>Update an item</span>  
                  </a>   
                  <a href="#" className={`${styles.button}`} onClick={() => this.deleteItem()}>  
                    <span className={styles.label}>Delete an item</span>  
                  </a>  
                </div>  
              </div>  
  
              <div className={`ms-Grid-row ms-bgColor-themeDark ms-fontColor-white ${styles.row}`}>  
                <div className='ms-Grid-col ms-u-lg10 ms-u-xl8 ms-u-xlPush2 ms-u-lgPush1'>  
                  {this.state.status}  
                  <ul>  
                    {items}  
                  </ul>  
                </div>  
              </div>  
  
            </div>  
          </div>  
        </div>  
      </div>  
    );  
  }  


  private getLatestItemId(): Promise<number> {  
    return new Promise<number>((resolve: (itemId: number) => void, reject: (error: any) => void): void => {  
      this.props.spHttpClient.get(`${this.props.siteUrl}/_api/web/lists/getbytitle('${this.props.listName}')/items?$orderby=Id desc&$top=1&$select=id`,  
        SPHttpClient.configurations.v1,  
        {  
          headers: {  
            'Accept': 'application/json;odata=nometadata',  
            'odata-version': ''  
          }  
        })  
        .then((response: SPHttpClientResponse): Promise<{ value: { Id: number }[] }> => {  
          return response.json();  
        }, (error: any): void => {  
          reject(error);  
        })  
        .then((response: { value: { Id: number }[] }): void => {  
          if (response.value.length === 0) {  
            resolve(-1);  
          }  
          else {  
            resolve(response.value[0].Id);  
          }  
        });  
    });  
  }   


  private createItem(): void {  
    this.setState({  
      status: 'Creating item...',  
      items: []  
    });  
    
    const body: string = JSON.stringify({  
      'Title': `Test item created by SPFx ReactJS on: ${new Date()}`  
    });  
    
    this.props.spHttpClient.post(`${this.props.siteUrl}/_api/web/lists/getbytitle('${this.props.listName}')/items`,  
    SPHttpClient.configurations.v1,  
    {  
      headers: {  
        'Accept': 'application/json;odata=nometadata',  
        'Content-type': 'application/json;odata=nometadata',  
        'odata-version': ''  
      },  
      body: body  
    })  
    .then((response: SPHttpClientResponse): Promise<IListItem> => {  
      return response.json();  
    })  
    .then((item: IListItem): void => {  
      this.setState({  
        status: `Item '${item.Title}' (ID: ${item.Id}) successfully created`,  
        items: []  
      });  
    }, (error: any): void => {  
      this.setState({  
        status: 'Error while creating the item: ' + error,  
        items: []  
      });  
    });  
  }  
  
  private readItem(): void {  
    this.setState({  
      status: 'Loading latest items...',  
      items: []  
    });  
    
    this.getLatestItemId()  
      .then((itemId: number): Promise<SPHttpClientResponse> => {  
        if (itemId === -1) {  
          throw new Error('No items found in the list');  
        }  
    
        this.setState({  
          status: `Loading information about item ID: ${itemId}...`,  
          items: []  
        });  
        return this.props.spHttpClient.get(`${this.props.siteUrl}/_api/web/lists/getbytitle('${this.props.listName}')/items(${itemId})?$select=Title,Id`,  
          SPHttpClient.configurations.v1,  
          {  
            headers: {  
              'Accept': 'application/json;odata=nometadata',  
              'odata-version': ''  
            }  
          });  
      })  
      .then((response: SPHttpClientResponse): Promise<IListItem> => {  
        return response.json();  
      })  
      .then((item: IListItem): void => {  
        this.setState({  
          status: `Item ID: ${item.Id}, Title: ${item.Title}`,  
          items: []  
        });  
      }, (error: any): void => {  
        this.setState({  
          status: 'Loading latest item failed with error: ' + error,  
          items: []  
        });  
      });  
  }  
  
  private updateItem(): void {  
    this.setState({  
      status: 'Loading latest items...',  
      items: []  
    });  
    
    let latestItemId: number = undefined;  
    
    this.getLatestItemId()  
      .then((itemId: number): Promise<SPHttpClientResponse> => {  
        if (itemId === -1) {  
          throw new Error('No items found in the list');  
        }  
    
        latestItemId = itemId;  
        this.setState({  
          status: `Loading information about item ID: ${latestItemId}...`,  
          items: []  
        });  
          
        return this.props.spHttpClient.get(`${this.props.siteUrl}/_api/web/lists/getbytitle('${this.props.listName}')/items(${latestItemId})?$select=Title,Id`,  
          SPHttpClient.configurations.v1,  
          {  
            headers: {  
              'Accept': 'application/json;odata=nometadata',  
              'odata-version': ''  
            }  
          });  
      })  
      .then((response: SPHttpClientResponse): Promise<IListItem> => {  
        return response.json();  
      })  
      .then((item: IListItem): void => {  
        this.setState({  
          status: 'Loading latest items...',  
          items: []  
        });  
    
        const body: string = JSON.stringify({  
          'Title': `Updated Item ${new Date()}`  
        });  
    
        this.props.spHttpClient.post(`${this.props.siteUrl}/_api/web/lists/getbytitle('${this.props.listName}')/items(${item.Id})`,  
          SPHttpClient.configurations.v1,  
          {  
            headers: {  
              'Accept': 'application/json;odata=nometadata',  
              'Content-type': 'application/json;odata=nometadata',  
              'odata-version': '',  
              'IF-MATCH': '*',  
              'X-HTTP-Method': 'MERGE'  
            },  
            body: body  
          })  
          .then((response: SPHttpClientResponse): void => {  
            this.setState({  
              status: `Item with ID: ${latestItemId} successfully updated`,  
              items: []  
            });  
          }, (error: any): void => {  
            this.setState({  
              status: `Error updating item: ${error}`,  
              items: []  
            });  
          });  
      });  
  }   
  
  

  private deleteItem(): void
   {  
    if (!window.confirm('Are you sure you want to delete the latest item?'))
     {  
      return;  
     }  
    
    this.setState({  
      status: 'Loading latest items...',  
      items: []  
    });  
    
    let latestItemId: number = undefined;  
    let etag: string = undefined;  
    this.getLatestItemId()  
      .then((itemId: number): Promise<SPHttpClientResponse> => {  
        if (itemId === -1) {  
          throw new Error('No items found in the list');  
        }  
    
        latestItemId = itemId;  
        this.setState({  
          status: `Loading information about item ID: ${latestItemId}...`,  
          items: []  
        });  
    
        return this.props.spHttpClient.get(`${this.props.siteUrl}/_api/web/lists/getbytitle('${this.props.listName}')/items(${latestItemId})?$select=Id`,  
          SPHttpClient.configurations.v1,  
          {  
            headers: {  
              'Accept': 'application/json;odata=nometadata',  
              'odata-version': ''  
            }  
          });  
      })  
      .then((response: SPHttpClientResponse): Promise<IListItem> => {  
        etag = response.headers.get('ETag');  
        return response.json();  
      })  
      .then((item: IListItem): Promise<SPHttpClientResponse> => {  
        this.setState({  
          status: `Deleting item with ID: ${latestItemId}...`,  
          items: []  
        });  
    
        return this.props.spHttpClient.post(`${this.props.siteUrl}/_api/web/lists/getbytitle('${this.props.listName}')/items(${item.Id})`,  
          SPHttpClient.configurations.v1,  
          {  
            headers: {  
              'Accept': 'application/json;odata=nometadata',  
              'Content-type': 'application/json;odata=verbose',  
              'odata-version': '',  
              'IF-MATCH': etag,  
              'X-HTTP-Method': 'DELETE'  
            }  
          });  
      })  
      .then((response: SPHttpClientResponse): void => {  
        this.setState({  
          status: `Item with ID: ${latestItemId} successfully deleted`,  
          items: []  
        });  
      }, (error: any): void => {  
        this.setState({  
          status: `Error deleting item: ${error}`,  
          items: []  
        });  
      });  
  }  

}


Demo: Test the ReactCRUD web part from the SharePoint Online site (_layouts/15/workbench.aspx)

To test the web part steps are below at high level:

  1. On the command prompt, type “gulp serve”
  2. Open SharePoint site where you want to test this web part.
  3. Navigate to /_layouts/15/workbench.aspx
  4. Add the webpart to page.
  5. Edit web part, in the properties pane, type the list name
  6. Click the buttons (Create an Item, Read an Item, Update an Item, and Delete an Item) one by one to test the web part
  7. Verify the operations are taking place in the SharePoint list by navigating to the list.

Example of /_layouts/15/workbench.aspx URL:

https://globalsharepoint2020.sharepoint.com/sites/allcompany/_layouts/15/workbench.aspx

Note:

  • Replace the site URL part with your URL.

Launch the web part in SharePoint Online page

Open this URL – https://globalsharepoint2020.sharepoint.com/sites/allcompany/_layouts/15/workbench.aspx

Your web part will not appear in the toolbox - Please make sure "gulp serve" is running in a web part project
Your web part will not appear in the toolbox – Please make sure “gulp serve” is running in a web part project

Once I opened the above URL, I got this warning message “Your web part will not appear in the toolbox. Please make sure “gulp serve” is running in a web part project. Please refresh the page once “gulp serve” is running.

Lets fix this above warning message. To fix this issue, we just need to open this URL – https://localhost:4321/temp/manifests.js in another tab, and need to accept the warning message.

Note:

  • The warning message might vary browser to browser, I got the above warning message in Mozilla Firefox, however, I didn’t get both in google chrome and edge browser.

The React CRUD web part in my edge browser:

The React CRUD web part in my edge browser
The React CRUD web part in my edge browser

Test the Create an list item operation: Create list item in SharePoint Online using SPFx React JS framework

Configure the list, here as part of the demo I have configured list “TestList”.

Note:

  • The list must be existed in the site before we do the CRUD operation, otheriwse w will gent an error message.
Create list item in SharePoint Online using SPFx React JS framework
Create list item in SharePoint Online using SPFx React JS framework

Verify the created list item from SharePoint Online list:

We can see that a new item got created thoguh the ReactCRUD create an item event.

Verification - Create list item in SharePoint Online using SPFx React JS framework

Read list item from SharePoint Online list using SPFx React JS framework

Read list item from SharePoint Online list using SPFx React JS framework
Read list item from SharePoint Online list using SPFx React JS framework

Update list item in SharePoint Online list using SPFx React JS framework

Update list item in SharePoint Online list using SPFx React JS framework
Update list item in SharePoint Online list using SPFx React JS framework

Delete list item from SharePoint Online list using SPFx React JS framework

Delete list item from SharePoint Online list using SPFx React JS framework
Delete list item from SharePoint Online list using SPFx React JS framework

Verification – Delete list item from SharePoint Online list using SPFx React JS framework

The list item what was just created sometimes back, now it is not avialble because it has been deleted through the React SPFx delete event handler.

Verification - Delete list item from SharePoint Online list using SPFx React JS framework
Verification – Delete list item from SharePoint Online list using SPFx React JS framework

Source Code

The source Code for the CRUD operation using the SPFx React framework is available here.

Summary

Thus in this article, we have learned how we can do the CRUD operation in SharePoint online list using the SPFx React JS framework.

See Also

You may also like the below SharePoint SPFx articles:

Free download SharePoint Online & Office 365 Administration eBook(238 Pages)

Get the PDF eBook from here:


 
FREE DOWNLOAD

Send download link to:

Subscribe to get exclusive content and recommendations every month. You can unsubscribe anytime.

 

1 comments on “SharePoint Online: CRUD operations using SPFx ReactJS framework”