Wednesday, 21 June 2023

Basic CRUD operations in React JS app using .NET Core web API

 In this article, we will create a react js app which provides list, create, update and delete function to users.

Pre-requisit: you should have basic knowledge of JavaScript, HTML, React JS and also have backend API which supports the List, Create, Update and Delete operations for Employee.

In addion to above you must have Node.js and npm installed globally


Employee backend model:

    [Table("Employee")]

    public class Employee

    {

        [Key]

        public int Id { get; set; }

        public string Name { get; set; }

        public string ContactMobile { get; set; }

        public string EmailId { get; set; }

        public string Address { get; set; }

    }

Script to create database table:

CREATE TABLE [dbo].[Employee](

       [Id] [int] IDENTITY(100,1) NOT NULL,

       [Name] [nvarchar](50) NULL,

       [ContactMobile] [nvarchar](50) NULL,

       [EmailId] [nvarchar](50) NULL,

       [Address] [nvarchar](256) NULL

) ON [PRIMARY]


We will build a basic Employee Management Application using React JS with CRUD features:

  • Add Employee
  • List Employee
  • Update Employee
  • Delete Employee
  • View Employee

Following is the screenshot of the final version of our application -

  • List Employee


  • Add Employee

  • View Employee

  • Update Employee



Let's create a new react app step by step from scratch.

  • Create react app named "react-frontend"

        npx create-react-app react-frontend

Here is the final project structure of our React App:

We will create tte files marked in red box in next steps.





















  • We will create a new folder called components inside the src folder. Then create a new file called ListEmployeeComponent.jsx

Within this file, let's create a React class component named ListEmployeeComponent with the following content:

import React, { Component } from 'react'
import BackendService from '../services/BackendService'

class ListEmployeeComponent extends Component {
    constructor(props) {
        super(props)

        this.state = {
                employees: [],
        }
        this.addEmployee = this.addEmployee.bind(this);
        this.editEmployee = this.editEmployee.bind(this);
        this.deleteEmployee = this.deleteEmployee.bind(this);
    }

    deleteEmployee(Id){
        BackendService.deleteEmployee(Id).then( res => {
            this.setState({employees: this.state.employees.filter(employee => employee.Id !== Id)});
        });
    }
    viewEmployee(Id){
        this.props.history.push(`/view-employee/${Id}`);
    }
    editEmployee(Id){
        this.props.history.push(`/add-employee/${Id}`);
    }

    componentDidMount(){
        BackendService.getEmployees().then((res) => {
            this.setState({ employees: res.data});
        });
    }

    addEmployee(){
        this.props.history.push('/add-employee/_add');
    }

    render() {

        return (
            <div>
                 <div className = "row" style={{ display: "flex" }}>
                    <button className="btn btn-info" style={{ marginLeft: "auto" }} onClick={this.addEmployee}> Add Employee</button>
                 </div>
                 <br></br>
                 <div className = "row">
                        <table className = "table table-striped table-bordered">

                            <thead>
                                <tr>
                                    <th> Employee ID</th>
                                    <th> Employee Name</th>
                                    <th> Employee Mobile</th>
                                    <th> Employee Email</th>
                                    <th> Employee Address</th>
                                    <th> Actions</th>
                                </tr>
                            </thead>
                            <tbody>
                                {
                                    this.state.employees.map(
                                        employee =>
                                        <tr key = {employee.Id}>
                                             <td> { employee.Id} </td>
                                             <td> { employee.Name} </td>  
                                             <td> {employee.ContactMobile}</td>
                                             <td> {employee.EmailId}</td>
                                             <td> {employee.Address}</td>
                                             <td>
                                                 <button onClick={ () => this.editEmployee(employee.Id)} className="btn btn-info">Update </button>
                                                 <button style={{marginLeft: "10px"}} onClick={ () => this.deleteEmployee(employee.Id)} className="btn btn-danger">Delete </button>
                                                 <button style={{marginLeft: "10px"}} onClick={() => this.viewEmployee(employee.Id)} className="btn btn-info">View </button>
                                             </td>
                                        </tr>
                                    )
                                }
                            </tbody>
                        </table>

                 </div>
            </div>
        )
    }
}

export default ListEmployeeComponent

 

  •  Create a new file called ViewEmployeeComponent.jsx and copy & past the following content in the file.

import React, { Component } from 'react'
import BackendService from '../services/BackendService'

class ViewEmployeeComponent extends Component {
    constructor(props) {
        super(props)
        this.state = {
            Id: this.props.match.params.Id,
            employee: {}
        }
    }

    componentDidMount(){
        BackendService.getEmployeeById(this.state.Id).then( res => {
            this.setState({employee: res.data});
        })
    }
    viewEmployee(Id){
        this.props.history.push('/employees');
    }
   
    render() {
        return (
            <div>
                <br></br>
                <div className = "card col-md-6 offset-md-3">
                    <h3 className = "text-center"> View Employee Details</h3>
                    <div className = "card-body">
                    <div className = "row">
                            <label style={{fontWeight: 'bold'}}> Employee ID: </label>
                            <div> { this.state.employee.Id }</div>
                        </div>
                        <div className = "row">
                            <label style={{fontWeight: 'bold'}}> Employee Name: </label>
                            <div> { this.state.employee.Name }</div>
                        </div>
                        <div className = "row">
                            <label style={{fontWeight: 'bold'}}> Employee Mobile: </label>
                            <div> { this.state.employee.ContactMobile }</div>
                        </div>
                        <div className = "row">
                            <label style={{fontWeight: 'bold'}}> Employee Email: </label>
                            <div> { this.state.employee.EmailId }</div>
                        </div>
                        <div className = "row">
                            <label style={{fontWeight: 'bold'}}> Employee Address: </label>
                            <div> { this.state.employee.Address }</div>
                        </div>
                    </div>
                    <div className = "row" style={{ display: "flex" }}>
                    <button className="btn btn-info" style={{ marginLeft: "auto" }} onClick={ () => this.viewEmployee(this.state.Id)}>Go Back</button>
                 </div>
                </div>
            </div>
        )
    }
}

export default ViewEmployeeComponent

 

  •  Create a new file called CreateUpdateEmployeeComponent.jsx and copy & past the following content in the file.
import React, { Component } from 'react'
import BackendService from '../services/BackendService';

class CreateUpdateEmployeeComponent extends Component {
    constructor(props) {
        super(props)

        this.state = {
            // step 2
            Id: this.props.match.params.Id,
            Name: '',
            ContactMobile: '',
            EmailId: '',
            Address:''
        }
        this.changeNameHandler = this.changeNameHandler.bind(this);
        this.changeContactMobileHandler = this.changeContactMobileHandler.bind(this);
        this.changeEmailIdHandler = this.changeEmailIdHandler.bind(this);
        this.changeAddressHandler = this.changeAddressHandler.bind(this);
        this.saveOrUpdateEmployee = this.saveOrUpdateEmployee.bind(this);
    }

    // step 3
    componentDidMount(){

        // step 4
        if(this.state.Id === '_add'){
            return
        }else{
            BackendService.getEmployeeById(this.state.Id).then( (res) =>{
                let employee = res.data;
                this.setState({Name: employee.Name,
                    ContactMobile: employee.ContactMobile,
                    EmailId : employee.EmailId,
                    Address : employee.Address
                });
            });
        }        
    }
    saveOrUpdateEmployee = (e) => {
        e.preventDefault();
        let employee = {Name: this.state.Name, ContactMobile: this.state.ContactMobile, EmailId: this.state.EmailId,
            Address:this.state.Address ,Id: this.state.Id};
        console.log('employee => ' + JSON.stringify(employee));
        // step 5
        if(this.state.Id === '_add'){
            employee.Id = 0;
            BackendService.createEmployee(employee).then(res =>{
                this.props.history.push('/employees');
            });
        }else{
            BackendService.updateEmployee(employee, this.state.Id).then( res => {
                this.props.history.push('/employees');
            });
        }
    }
   
    changeNameHandler= (event) => {
        this.setState({Name: event.target.value});
    }

    changeContactMobileHandler= (event) => {
        this.setState({ContactMobile: event.target.value});
    }

    changeEmailIdHandler= (event) => {
        this.setState({EmailId: event.target.value});
    }
    changeAddressHandler= (event) => {
        this.setState({Address: event.target.value});
    }

    cancel(){
        this.props.history.push('/employees');
    }

    getTitle(){
        if(this.state.Id === '_add'){
            return <h3 className="text-center">Add Employee</h3>
        }else{
            return <h3 className="text-center">Update Employee</h3>
        }
    }
    render() {
        return (
            <div>
                <br></br>
                   <div className = "container">
                        <div className = "row">
                            <div className = "card col-md-6 offset-md-3 offset-md-3">
                                {
                                    this.getTitle()
                                }
                                <div className = "card-body">
                                    <form>
                                        <div className = "form-group">
                                            <label>Employee Name: </label>
                                            <input placeholder="Name" name="Name" className="form-control"
                                                value={this.state.Name} onChange={this.changeNameHandler}/>
                                        </div>
                                        <div className = "form-group">
                                            <label>Employee Mobile: </label>
                                            <input placeholder="ContactMobile" name="ContactMobile" className="form-control"
                                                value={this.state.ContactMobile} onChange={this.changeContactMobileHandler}/>
                                        </div>
                                        <div className = "form-group">
                                            <label>Employee Email: </label>
                                            <input placeholder="Email Id" name="EmailId" className="form-control"
                                                value={this.state.EmailId} onChange={this.changeEmailIdHandler}/>
                                        </div>
                                        <div className = "form-group">
                                            <label>Employee Address: </label>
                                            <input placeholder="Address" name="Address" className="form-control"
                                                value={this.state.Address} onChange={this.changeAddressHandler}/>
                                        </div>
                                        <button className="btn btn-success" onClick={this.saveOrUpdateEmployee}>Save</button>
                                        <button className="btn btn-danger" onClick={this.cancel.bind(this)} style={{marginLeft: "10px"}}>Cancel</button>
                                    </form>
                                </div>
                            </div>
                        </div>

                   </div>
            </div>
        )
    }
}

export default CreateUpdateEmployeeComponent

 

  •  Create a new file called FooterComponent.jsx and copy & past the following content in the file.
import React, { Component } from 'react'

class FooterComponent extends Component {
    constructor(props) {
        super(props)

        this.state = {
                 
        }
    }

    render() {
        return (
            <div>
                <footer className = "footer">
                    <span className="text-muted">All Rights Reserved 2023 rpsingh@react.com</span>
                </footer>
            </div>
        )
    }
}

export default FooterComponent

 

  •  Create a new file called HeaderComponent.jsx and copy & past the following content in the file.
import React, { Component } from 'react'

class HeaderComponent extends Component {
    constructor(props) {
        super(props)

        this.state = {
                 
        }
    }

    render() {
        return (
            <div>
                <header>
                    <nav className="navbar navbar-expand-md navbar-dark bg-dark">
                    <div><a href="https://rpsinghdotnetwcf.blogspot.com/" className="navbar-brand">Employee Management App</a></div>
                    </nav>
                </header>
            </div>
        )
    }
}

export default HeaderComponent

 

  • Create a new folder services and create backend service components file called BackendService.js and copy & past the following content in the file.
import axios from 'axios';
import qs from 'qs';

const EMPLOYEE_API_BASE_URL = "http://localhost:50306/api/Employee";

class BackendService {

    getEmployees(){
        return axios.get(EMPLOYEE_API_BASE_URL+'/GetEmployeeDetails');
    }

    createEmployee(employee){
        return axios.post(EMPLOYEE_API_BASE_URL+'/AddEmployee',  employee);
    }

    getEmployeeById(employeeId){
        return axios.get(EMPLOYEE_API_BASE_URL + '/GetEmployeeByID/' + employeeId);
    }

    updateEmployee(employee, employeeId){
        return axios.put(EMPLOYEE_API_BASE_URL + '/UpdateEmployee' , employee )
        .catch(error => {
            this.setState({ errorMessage: error.message });
            console.error('There was an error!', error.message)
        });
    }

    deleteEmployee(employeeId){
        return axios.delete(EMPLOYEE_API_BASE_URL + '/DeleteEmployee?Id=' + employeeId);
    }
}

export default new BackendService()


  •  Now copy & past the following content in the file App.js
import React from 'react';
import logo from './logo.svg';
import './App.css';
import {BrowserRouter as Router, Route, Switch, NavLink} from 'react-router-dom'
import ListEmployeeComponent from './components/ListEmployeeComponent';
import HeaderComponent from './components/HeaderComponent';
import FooterComponent from './components/FooterComponent';
import CreateUpdateEmployeeComponent from './components/CreateUpdateEmployeeComponent';
import ViewEmployeeComponent from './components/ViewEmployeeComponent';

function App() {
  return (
    <div>
        <Router>
              <HeaderComponent />
                <div className="container">

                <nav className="navbar navbar-expand-sm bg-light navbar-dark">
          <ul className="navbar-nav">
            <li className="nav-item m-1">
              <NavLink className="btn btn-info" style={{ marginLeft: "auto" }} to="/">
                Home
              </NavLink>
            </li>
          </ul>
        </nav>

                    <Switch>
                          <Route path = "/" exact component = {ListEmployeeComponent}></Route>
                          <Route path = "/employees" component = {ListEmployeeComponent}></Route>
                          <Route path = "/add-employee/:Id" component = {CreateUpdateEmployeeComponent}></Route>
                          <Route path = "/view-employee/:Id" component = {ViewEmployeeComponent}></Route>
                          {/* <Route path = "/update-employee/:id" component = {UpdateEmployeeComponent}></Route> */}
                    </Switch>
                </div>
              <FooterComponent />
        </Router>
    </div>
   
  );
}

export default App;


  • Finally, use the below command to start the project:

PS D:\Project\React App\react-frontend> npm start


Note: Before running React App, make sure that your backend API is up and running.