SPFx CRUD operations using React Framework code

props.ts: ICrudwithreactwebpart.ts

import { WebPartContext } from "@microsoft/sp-webpart-base";

export interface ICrudWithReactWebPartProps {
  description: string;
  context:WebPartContext;
  siteUrl: string;
}
-------------
main.ts
CrudWithReactWebPart,
      {
        description: this.properties.description,
        context:this.context,
        siteUrl:this.context.pageContext.web.absoluteUrl
      }
----------------
State file: ICrudWithReactState.ts
import { ISoftwareListItem } from "./ISoftwareListItem";

export interface ICrudWithReactState{
    status: string;
    SoftwareListItems: ISoftwareListItem[];
    SoftwareListItem: ISoftwareListItem;
}
-----------
interface: ISoftwareListItem.ts
export interface ISoftwareListItem{
    Id:number;
    Title:string;
    SoftwareName: string;
    SoftwareVendor: string;
    SoftwareVersion: string;
    SoftwareDescription: string;
}
------------------------
Note: in tsx file, auto bind property onChange
npm i autobind-decorator
import autobind from 'autobind-decorator';

-------------
.tsx file

import * as React from 'react';
import styles from './CrudWithReactWebPart.module.scss';
import { ICrudWithReactWebPartProps } from './ICrudWithReactWebPartProps';
import { escape } from '@microsoft/sp-lodash-subset';
import { ISoftwareListItem } from './ISoftwareListItem';
import { ICrudWithReactState } from './ICrudWithReactState';

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

import { TextField, PrimaryButton, DetailsList, DetailsListLayoutMode, CheckboxVisibility, SelectionMode, Dropdown, IDropdown, IDropdownOption, ITextFieldStyles, IDropdownStyles, DetailsRowCheck, Selection } from 'office-ui-fabric-react';
import autobind from 'autobind-decorator';


//configure columns for the details list component
let _softwareListColumns = [
  {
    key: 'ID',
    name: 'ID',
    fieldName: 'ID',
    minWidth: 50,
    maxWidth: 100,
    isResizable: true
  },
  {
    key: 'Title',
    name: 'Title',
    fieldName: 'Title',
    minWidth: 50,
    maxWidth: 100,
    isResizable: true
  },
  {
    key: 'SoftwareName',
    name: 'SoftwareName',
    fieldName: 'SoftwareName',
    minWidth: 50,
    maxWidth: 100,
    isResizable: true
  },
  {
    key: 'SoftwareVendor',
    name: 'SoftwareVendor',
    fieldName: 'SoftwareVendor',
    minWidth: 50,
    maxWidth: 100,
    isResizable: true
  },
  {
    key: 'SoftwareVersion',
    name: 'SoftwareVersion',
    fieldName: 'SoftwareVersion',
    minWidth: 50,
    maxWidth: 100,
    isResizable: true
  },
  {
    key: 'SoftwareDescription',
    name: 'SoftwareDescription',
    fieldName: 'SoftwareDescription',
    minWidth: 50,
    maxWidth: 100,
    isResizable: true
  }
];

const textFieldStyles: Partial<ITextFieldStyles> = { fieldGroup: { width: 300 } };
const narrowTextFields: Partial<ITextFieldStyles> = { fieldGroup: { width: 300 } };
const narrowDropdownStyles: Partial<IDropdownStyles> = { dropdown: { width: 300 } };

export default class CrudWithReactWebPart extends React.Component<ICrudWithReactWebPartProps, ICrudWithReactState> {


  private _selection: Selection;
  private _onItemsSelectionChanged = () =>{
    this.setState({
      SoftwareListItem:(this._selection.getSelection()[0] as ISoftwareListItem)
    });
  }

  constructor(props: ICrudWithReactWebPartProps, state: ICrudWithReactState) {
    super(props);
    this.state = {
      status: 'Ready',
      SoftwareListItems: [],
      SoftwareListItem: {
        Id: 0,
        Title: "",
        SoftwareName: "",
        SoftwareVendor: "Select an Option",
        SoftwareVersion: "",
        SoftwareDescription: ""
      }
    };

    this._selection = new Selection({
      onSelectionChanged:this._onItemsSelectionChanged,
    });
   
  }

  private _getListItems():Promise<ISoftwareListItem[]>{
    const url:string = this.props.siteUrl+"/_api/web/lists/getbytitle('SoftwareCatalog')/items";
    return this.props.context.spHttpClient.get(url,SPHttpClient.configurations.v1)
    .then(response =>{
      return response.json();
    })
    .then(json=>{
      return json.value;
    }) as Promise<ISoftwareListItem[]>;
  }

  public componentDidMount():void{
    this.bindDetailsList("All records have been loaded successfully");
  }
 
  @autobind
  public btnAdd_click():void{
    debugger;

    const url: string = this.props.siteUrl + "/_api/web/lists/getbytitle('SoftwareCatalog')/items";
   
    const SPHttpClientOptions:ISPHttpClientOptions = {
      "body":JSON.stringify(this.state.SoftwareListItem)
    };

    this.props.context.spHttpClient.post(url,SPHttpClient.configurations.v1,SPHttpClientOptions).then((response:SPHttpClientResponse) => {
      if(response.status === 201){
        alert("record has been added successfully");
        this.bindDetailsList("Record Added and All records loaded successfully!");
      }
      else{
        let errormessage: string = "An error occured. i.e "+response.status+" - "+response.statusText;
        this.setState({
          status:errormessage
        });
      }
    });
  }

  @autobind
  public btnUpdate_click():void{
    debugger;
    let id:number=this.state.SoftwareListItem.Id;

    const url: string = this.props.siteUrl + "/_api/web/lists/getbytitle('SoftwareCatalog')/items("+id+")";

    const headers:any={
      "X-HTTP-Method":"MERGE",
      "IF-MATCH":"*"
    };
   
    const SPHttpClientOptions:ISPHttpClientOptions = {
      "headers":headers,
      "body":JSON.stringify(this.state.SoftwareListItem)
    };

    this.props.context.spHttpClient.post(url,SPHttpClient.configurations.v1,SPHttpClientOptions).then((response:SPHttpClientResponse) => {
      if(response.status === 204){
        alert("record has been updated successfully");
        this.bindDetailsList("Record Updated and All loaded are updated successfully!");
      }
      else{
        let errormessage: string = "An error occured. i.e "+response.status+" - "+response.statusText;
        this.setState({
          status:errormessage
        });
      }
    });
  }

  @autobind
  public btnDelete_click():void{
    debugger;
    let id:number=this.state.SoftwareListItem.Id;

    const url: string = this.props.siteUrl + "/_api/web/lists/getbytitle('SoftwareCatalog')/items("+id+")";

    const headers:any={
      "X-HTTP-Method":"DELETE",
      "IF-MATCH":"*"
    };
   
    const SPHttpClientOptions:ISPHttpClientOptions = {
      "headers":headers
    };

    this.props.context.spHttpClient.post(url,SPHttpClient.configurations.v1,SPHttpClientOptions).then((response:SPHttpClientResponse) => {
      if(response.status === 204){
        alert("record has been deleted successfully");
        this.bindDetailsList("Record Deleted and All records loaded successfully!");
      }
      else{
        let errormessage: string = "An error occured. i.e "+response.status+" - "+response.statusText;
        this.setState({
          status:errormessage
        });
      }
    });
  }
  public bindDetailsList(message:string):void{
    this._getListItems().then(listItems=>{
      this.setState({
        SoftwareListItems:listItems,
        status:message
      });
    });
  }


  private onChangeIDField(event: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>, newValue: string): void {
    this.setState({
      SoftwareListItem:{
        Id:Number(newValue),
        Title:this.state.SoftwareListItem.Title,
        SoftwareName: this.state.SoftwareListItem.SoftwareName,
        SoftwareVendor: this.state.SoftwareListItem.SoftwareVendor,
        SoftwareVersion: this.state.SoftwareListItem.SoftwareVersion,
        SoftwareDescription:this.state.SoftwareListItem.SoftwareDescription
      }
    });
  }
  private onChangeTitleField(event: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>, newValue: string): void {
    this.setState({
      SoftwareListItem:{
        Id:this.state.SoftwareListItem.Id,
        Title:newValue,
        SoftwareName: this.state.SoftwareListItem.SoftwareName,
        SoftwareVendor: this.state.SoftwareListItem.SoftwareVendor,
        SoftwareVersion: this.state.SoftwareListItem.SoftwareVersion,
        SoftwareDescription:this.state.SoftwareListItem.SoftwareDescription
      }
    });
  }
  private onChangeSoftwareNameField(event: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>, newValue: string): void {
    this.setState({
      SoftwareListItem:{
        Id:this.state.SoftwareListItem.Id,
        Title:this.state.SoftwareListItem.Title,
        SoftwareName: newValue,
        SoftwareVendor: this.state.SoftwareListItem.SoftwareVendor,
        SoftwareVersion: this.state.SoftwareListItem.SoftwareVersion,
        SoftwareDescription:this.state.SoftwareListItem.SoftwareDescription
      }
    });
  }
  private onChangeDescriptionField(event: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>, newValue: string): void {
    this.setState({
      SoftwareListItem:{
        Id:this.state.SoftwareListItem.Id,
        Title:this.state.SoftwareListItem.Title,
        SoftwareName: this.state.SoftwareListItem.SoftwareName,
        SoftwareVendor: this.state.SoftwareListItem.SoftwareVendor,
        SoftwareVersion: this.state.SoftwareListItem.SoftwareVersion,
        SoftwareDescription:newValue
      }
    });
  }
  private onChangeSoftwareVersionField(event: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>, newValue: string): void {
    this.setState({
      SoftwareListItem:{
        Id:this.state.SoftwareListItem.Id,
        Title:this.state.SoftwareListItem.Title,
        SoftwareName: this.state.SoftwareListItem.SoftwareName,
        SoftwareVendor: this.state.SoftwareListItem.SoftwareVendor,
        SoftwareVersion: newValue,
        SoftwareDescription:this.state.SoftwareListItem.SoftwareDescription
      }
    });
  }
  private onChangeDropDownField(event: React.FormEvent<HTMLDivElement>, option?: IDropdownOption, index?: number): void {
    console.log(option.text);
    this.setState({
      SoftwareListItem:{
        Id:this.state.SoftwareListItem.Id,
        Title:this.state.SoftwareListItem.Title,
        SoftwareName: this.state.SoftwareListItem.SoftwareName,
        SoftwareVendor: option.text,
        SoftwareVersion: this.state.SoftwareListItem.SoftwareVersion,
        SoftwareDescription: this.state.SoftwareListItem.SoftwareDescription
      }
    });
  }

  public render(): React.ReactElement<ICrudWithReactWebPartProps> {

    const dropdownRef = React.createRef<IDropdown>();

    return (
      <div className={styles.crudWithReactWebPart}>
        <TextField
          label="ID"
          required={false}
          value={(this.state.SoftwareListItem.Id).toString()}
          styles={textFieldStyles}
          onChange={this.onChangeIDField.bind(this)}
        />
        <TextField
          label="Software Title"
          required={false}
          value={(this.state.SoftwareListItem.Title).toString()}
          styles={textFieldStyles}
          onChange={this.onChangeTitleField.bind(this)}
        />
        <TextField
          label="Software Name"
          required={false}
          value={(this.state.SoftwareListItem.SoftwareName).toString()}
          styles={textFieldStyles}
          onChange={this.onChangeSoftwareNameField.bind(this)}
        />
        <TextField
          label="Software Description"
          required={false}
          value={(this.state.SoftwareListItem.SoftwareDescription).toString()}
          styles={textFieldStyles}
          onChange={this.onChangeDescriptionField.bind(this)}
        />
        <TextField
          label="Software Version"
          required={false}
          value={(this.state.SoftwareListItem.SoftwareVersion).toString()}
          styles={textFieldStyles}
          onChange={this.onChangeSoftwareVersionField.bind(this)}
        />
        <Dropdown
          componentRef={dropdownRef}
          placeholder="select an option"
          label="Software Vendor"
          options={[
            { key: 'Microsoft', text: 'Microsoft' },
            { key: 'Sun', text: 'Sun' },
            { key: 'Oracle', text: 'Oracle' },
            { key: 'Google', text: 'Google' }
          ]}
          defaultSelectedKey={this.state.SoftwareListItem.SoftwareVendor}
          required
          styles={narrowDropdownStyles}
          onChange={this.onChangeDropDownField.bind(this)}
        />
        <br/>
        <PrimaryButton
          text='Add'
          title='Add'
          onClick={this.btnAdd_click}
        />
        &nbps;
        <PrimaryButton
          text='Update'
          title='Update'
          onClick={this.btnUpdate_click}
        />
        &nbps;
        <PrimaryButton
          text='Delete'
          title='Delete'
          onClick={this.btnDelete_click}
        />
        <br/>
        <div id="divStatus">
          {this.state.status}
        </div>

        <p className={styles.title}>
          <div>
            <DetailsList
              items={this.state.SoftwareListItems}
              columns={_softwareListColumns}
              setKey='Id'
              checkboxVisibility={CheckboxVisibility.always}
              selectionMode={SelectionMode.single}
              layoutMode={DetailsListLayoutMode.fixedColumns}
              compact={true}
              selection={this._selection}

            />
          </div>
        </p>
      </div>
    );
  }
}


Comments