SharePoint Framework CRUD Operations using SPHttpClient
- Create a list with Name EmployeeDetails. Add column Age. We will use the Title column to Save the Full name and the Age column to add the age of the employee.
- I have created a folder with the name SPFxCrud on your local machine under the E folder.
- Copy the folder path and open the path in the command prompt by using the below command:1
cd E:\Office365Notes\SPFxCrud
- Scaffold the SPFx solution using Yeoman Generator1
yo @microsoft/sharepoint
- Give the webpart name and other details as shown below
- Open the solution in VS Code. You can use the "Code ." command in the command prompt directly to open the solution in VS Code.
- We are going to write the entire logic for CRUD operations in the .tsx file. For that, we need the context of SharePoint in the .tsx file.
- We will first define a property for passing the SharePoint context from our .ts file to the .tsx file.
- Add a property context in the ISpFxCrudProps.ts file as shown below:1234
export interface ISpFxCrudProps {
description: string;
context: any;
}
- Then initialize the context from the SpFxCrudWebPart.ts file as shown below
- Update the default HTML (JSX) in SPFxCrud.tsx with below HTML (JSX)123456789101112131415161718192021222324252627282930313233343536373839404142
<div className={styles.helloWorldReact}>
<div className={styles.container}>
<div className={styles.row}>
<div className={styles.column}>
<p className={styles.description}>{escape(
this
.props.description)}</p>
<div className={styles.itemField}>
<div className={styles.fieldLabel}>Item ID:</div>
<input type=
"text"
id=
'itemId'
></input>
</div>
<div className={styles.itemField}>
<div className={styles.fieldLabel}>Full Name</div>
<input type=
"text"
id=
'fullName'
></input>
</div>
<div className={styles.itemField}>
<div className={styles.fieldLabel}>Age</div>
<input type=
"text"
id=
'age'
></input>
</div>
<div className={styles.itemField}>
<div className={styles.fieldLabel}>All Items:</div>
<div id=
"allItems"
></div>
</div>
<div className={styles.buttonSection}>
<div className={styles.button}>
<span className={styles.label} onClick={
this
.createItem}>Create</span>
</div>
<div className={styles.button}>
<span className={styles.label} onClick={
this
.getItemById}>Read</span>
</div>
<div className={styles.button}>
<span className={styles.label} onClick={
this
.getAllItems}>Read All</span>
</div>
<div className={styles.button}>
<span className={styles.label} onClick={
this
.updateItem}>Update</span>
</div>
<div className={styles.button}>
<span className={styles.label} onClick={
this
.deleteItem}>Delete</span>
</div>
</div>
</div>
</div>
</div>
</div>
- Import the below libraries in the file at the top, where other dependencies are imported.1234
import {
SPHttpClient,
SPHttpClientResponse
} from
'@microsoft/sp-http'
;
- When we will add the functions for CRUD Operations, our tax file will look like below
- When you add the functions for CRUD Operations, your .tsx file will look like below:123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
import * as React from
'react'
;
import styles from
'./SpFxCrud.module.scss'
;
import { ISpFxCrudProps } from
'./ISpFxCrudProps'
;
import { escape } from
'@microsoft/sp-lodash-subset'
;
import {
SPHttpClient,
SPHttpClientResponse
} from
'@microsoft/sp-http'
;
export
default
class SpFxCrud extends React.Component<ISpFxCrudProps, {}> {
public render(): React.ReactElement<ISpFxCrudProps> {
return
(
<div className={styles.SpFxCrud}>
<div className={styles.container}>
<div className={styles.row}>
<div className={styles.column}>
<p className={styles.description}>{escape(
this
.props.description)}</p>
<div className={styles.itemField}>
<div className={styles.fieldLabel}>Item ID:</div>
<input type=
"text"
id=
'itemId'
></input>
</div>
<div className={styles.itemField}>
<div className={styles.fieldLabel}>Full Name</div>
<input type=
"text"
id=
'fullName'
></input>
</div>
<div className={styles.itemField}>
<div className={styles.fieldLabel}>Age</div>
<input type=
"text"
id=
'age'
></input>
</div>
<div className={styles.itemField}>
<div className={styles.fieldLabel}>All Items:</div>
<div id=
"allItems"
></div>
</div>
<div className={styles.buttonSection}>
<div className={styles.button}>
<span className={styles.label} onClick={
this
.createItem}>Create</span>
</div>
<div className={styles.button}>
<span className={styles.label} onClick={
this
.getItemById}>Read</span>
</div>
<div className={styles.button}>
<span className={styles.label} onClick={
this
.getAllItems}>Read All</span>
</div>
<div className={styles.button}>
<span className={styles.label} onClick={
this
.updateItem}>Update</span>
</div>
<div className={styles.button}>
<span className={styles.label} onClick={
this
.deleteItem}>Delete</span>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
// Create Item
private createItem = (): void => {
const body: string = JSON.stringify({
'Title'
: document.getElementById(
"fullName"
)[
'value'
],
'Age'
: document.getElementById(
"age"
)[
'value'
]
});
this
.props.context.spHttpClient.post(`${
this
.props.context.pageContext.web.absoluteUrl}/_api/web/lists/getbytitle(
'EmployeeDetails'
)/items`,
SPHttpClient.configurations.v1, {
headers: {
'Accept'
:
'application/json;odata=nometadata'
,
'Content-type'
:
'application/json;odata=nometadata'
,
'odata-version'
:
''
},
body: body
})
.then((response: SPHttpClientResponse) => {
if
(response.ok) {
response.json().then((responseJSON) => {
console.log(responseJSON);
alert(`Item created successfully
with
ID: ${responseJSON.ID}`);
});
}
else
{
response.json().then((responseJSON) => {
console.log(responseJSON);
alert(`Something went wrong! Check the error
in
the browser console.`);
});
}
}).
catch
(error => {
console.log(error);
});
}
// Get Item by ID
private getItemById = (): void => {
const id: number = document.getElementById(
'itemId'
)[
'value'
];
if
(id > 0) {
this
.props.context.spHttpClient.get(
this
.props.context.pageContext.web.absoluteUrl + `/_api/web/lists/getbytitle(
'EmployeeDetails'
)/items(${id})`,
SPHttpClient.configurations.v1,
{
headers: {
'Accept'
:
'application/json;odata=nometadata'
,
'odata-version'
:
''
}
})
.then((response: SPHttpClientResponse) => {
if
(response.ok) {
response.json().then((responseJSON) => {
console.log(responseJSON);
document.getElementById(
'fullName'
)[
'value'
] = responseJSON.Title;
document.getElementById(
'age'
)[
'value'
] = responseJSON.Age;
});
}
else
{
response.json().then((responseJSON) => {
console.log(responseJSON);
alert(`Something went wrong! Check the error
in
the browser console.`);
});
}
}).
catch
(error => {
console.log(error);
});
}
else
{
alert(`Please enter a valid item id.`);
}
}
// Get all items
private getAllItems = (): void => {
this
.props.context.spHttpClient.get(
this
.props.context.pageContext.web.absoluteUrl + `/_api/web/lists/getbytitle(
'EmployeeDetails'
)/items`,
SPHttpClient.configurations.v1,
{
headers: {
'Accept'
:
'application/json;odata=nometadata'
,
'odata-version'
:
''
}
})
.then((response: SPHttpClientResponse) => {
if
(response.ok) {
response.json().then((responseJSON) => {
var
html = `<table><tr><th>ID</th><th>Full Name</th><th>Age</th></tr>`;
responseJSON.value.map((item, index) => {
html += `<tr><td>${item.ID}</td><td>${item.Title}</td><td>${item.Age}</td></li>`;
});
html += `</table>`;
document.getElementById(
"allItems"
).innerHTML = html;
console.log(responseJSON);
});
}
else
{
response.json().then((responseJSON) => {
console.log(responseJSON);
alert(`Something went wrong! Check the error
in
the browser console.`);
});
}
}).
catch
(error => {
console.log(error);
});
}
// Update Item
private updateItem = (): void => {
const id: number = document.getElementById(
'itemId'
)[
'value'
];
const body: string = JSON.stringify({
'Title'
: document.getElementById(
"fullName"
)[
'value'
],
'Age'
: document.getElementById(
"age"
)[
'value'
]
});
if
(id > 0) {
this
.props.context.spHttpClient.post(`${
this
.props.context.pageContext.web.absoluteUrl}/_api/web/lists/getbytitle(
'EmployeeDetails'
)/items(${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) => {
if
(response.ok) {
alert(`Item
with
ID: ${id} updated successfully!`);
}
else
{
response.json().then((responseJSON) => {
console.log(responseJSON);
alert(`Something went wrong! Check the error
in
the browser console.`);
});
}
}).
catch
(error => {
console.log(error);
});
}
else
{
alert(`Please enter a valid item id.`);
}
}
// Delete Item
private deleteItem = (): void => {
const id: number = parseInt(document.getElementById(
'itemId'
)[
'value'
]);
if
(id > 0) {
this
.props.context.spHttpClient.post(`${
this
.props.context.pageContext.web.absoluteUrl}/_api/web/lists/getbytitle(
'EmployeeDetails'
)/items(${id})`,
SPHttpClient.configurations.v1,
{
headers: {
'Accept'
:
'application/json;odata=nometadata'
,
'Content-type'
:
'application/json;odata=verbose'
,
'odata-version'
:
''
,
'IF-MATCH'
:
'*'
,
'X-HTTP-Method'
:
'DELETE'
}
})
.then((response: SPHttpClientResponse) => {
if
(response.ok) {
alert(`Item ID: ${id} deleted successfully!`);
}
else
{
alert(`Something went wrong!`);
console.log(response.json());
}
});
}
else
{
alert(`Please enter a valid item id.`);
}
}
}
- You have to update the SpFxCrud.module.scss file with below CSS123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
@import "~office-ui-fabric-react/dist/sass/References.scss";
.SpFxCrud {
.container {
max-width: 700px;
margin: 0px auto;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
}
.row {
@include ms-Grid-row;
@include ms-fontColor-white;
background-color: $ms-color-themeDark;
padding: 20px;
}
.column {
@include ms-Grid-col;
@include ms-lg10;
@include ms-xl8;
@include ms-xlPush2;
@include ms-lgPush1;
}
.title {
@include ms-font-xl;
@include ms-fontColor-white;
}
.subTitle {
@include ms-font-l;
@include ms-fontColor-white;
}
.description {
@include ms-font-l;
@include ms-fontColor-white;
}
.button {
// Our button
text-decoration: none;
height: 32px;
// Primary Button
min-width: 80px;
background-color: $ms-color-themePrimary;
border-color: $ms-color-themePrimary;
color: $ms-color-white;
// Basic Button
outline: transparent;
position: relative;
font-family: "Segoe UI WestEuropean", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue",
sans-serif;
-webkit-font-smoothing: antialiased;
font-size: $ms-font-size-m;
font-weight: $ms-font-weight-regular;
border-width: 0;
text-align: center;
cursor: pointer;
display: inline-block;
margin: 10px;
.label {
font-weight: $ms-font-weight-semibold;
font-size: $ms-font-size-m;
height: 32px;
line-height: 32px;
margin: 0 4px;
vertical-align: top;
display: inline-block;
}
}
.itemField {
display: flex;
padding: 5px;
.fieldLabel {
min-width: 100px;
}
}
.buttonSection{
padding-top: 20px;
display: flex;
}
}
- Your UI will look like as below