Inline Table editing with Edit and Delete Button Icon In React Js


In this tutorial, we'll explore how to conduct CRUD operations with inline table editing, incorporating edit icons and delete functionality in a React.js application utilizing a REST API.

In certain scenarios within our applications, there is a need to perform insert, update, and delete operations on records directly within a table using inline editing.

In our last article, we discussed crud operation in react js using rest api. In this post, We will discuses add edit records using table and bootstrap and icons.

Suppose we have one page in which we can see the list of staff in our company and we want to perform the crud operation instead of creating 4 components to perform these tasks we can create a single component to fulfill our requirements. So in this article, we will perform add, edit and delete rows of an HTML table with the help of bootstrap and font awesome icon.

inline table editing with edit icon and delete in react js
inline table editing with edit icon and delete in react js

We are using free rest API for showing the demo

  1. GET http://samplerestapi.com/api/Touristget
  2. POST http://samplerestapi.com/api/TouristpostJPG
  3. PUT http://samplerestapi.com/api/Tourist/15863put
  4. DELETE  http://samplerestapi.com/api/Tourist/15863

If you want to read more about RESTful APIs – You can refer to the below link here we have given a sample rest API for testing purposes.

Add action icons (edit, delete) in table using React,js

  • Create react js app using the below command

npx create-react-app crud-app

  • Install bootstrap CSS and font-awesome  in our project using the below command

npm install bootstrap –save
npm install –save font-awesome

Create two folders called “httphelpers” and components in the src folder.

Inside httphelpers create one file restHelper.js and inside the components folder, create three files i.e Touristtable.js, Crudtourists.js, and Addtourist.js

reactjsproject

restHelper.js is a file that contains commonly used functions with static type. The benefit of creating such a helper class is that we can write all common functions in a single place file and can re-use them in any component so using a helper file, we can maintain code re-usability and maintainability.

In summary, below helper provides a convenient way to make HTTP requests (GET, POST, PUT, DELETE) to REST APIs using the Fetch API in JavaScript. It encapsulates common functionalities and error handling for making such requests.

restHelper.js

export const restHelper = () => {
    
const callAPI = async (endpointurl, options = {}) => {
const defaultHTTPMethod = "GET"
const defaultHTTPHeaders = {  //set defaultHeaders of Http request
"Content-Type": "application/json",
            Accept: "application/json",
        }
const controller = new AbortController() //using  AbortController to cancel ongoing fetch requests
        options.signal = controller.signal

        options.method = options.method || defaultHTTPMethod

        options.headers = options.headers
            ? { ...defaultHTTPHeaders, ...options.headers }
            : defaultHTTPHeaders

        options.body = JSON.stringify(options.body) || false
if (!options.body) delete options.body

        setTimeout(() => { // cancel request if it will take more then 5s 
            controller.abort()
        }, 5000)

try {
const apiResponse = await fetch(endpointurl, options)
return await apiResponse.json()
        } catch (err) {
return err
        }
    }

//calling get API For fetching data
const get = (endpointurl, options = {}) => callAPI(endpointurl, options)

//Post to insert 
const postCreate = (endpointurl, options) => {
        options.method = "POST"
return callAPI(endpointurl, options)
    }


//Put Api calling
const putUpdate = (endpointurl, options) => {
        options.method = "PUT"
return callAPI(endpointurl, options)
    }

//Delete Api calling
const deletedata = (endpointurl, options) => {
        options.method = "DELETE"
return callAPI(endpointurl, options)
    }

return {
get,
        postCreate,
        putUpdate,
        deletedata,
    }
}

Touristtable.js

import React from "react"
import Form from "./Addtourist"
import 'bootstrap/dist/css/bootstrap.min.css';
import 'font-awesome/css/font-awesome.min.css';

const Touristtable = ({ tourists, postTourist, updateTourist, deleteTourist }) => {
    debugger;
const showUpdateUser = id => {
const form = document.getElementsByClassName(`show-form-${id}`)
        form[0].classList.toggle("hide-form")
    }

const Row = ({ tourist }) => {
return (
            <>
                <tr>
                    <td>{tourist.tourist_name}</td>
                    <td>{tourist.tourist_email}</td>
                    <td>{tourist.tourist_location}</td>
                    <td>
                        <i className="fa fa-pencil-square fa-2x text-info" onClick={() => showUpdateUser(tourist.id)}></i>
                        <i className="fa fa-trash fa-2x text-danger" onClick={() => deleteTourist(tourist.id)}></i>    
                    </td>
                </tr>
                <tr className={`hide-form show-form-${tourist.id}`}> 
                   <Form userData={tourist} postTourist={postTourist} updateTourist={updateTourist} showUpdateUser={showUpdateUser} />
                </tr>
            </>
        )
    }

return (
        
            <table className="table">
                    <thead>
                        <tr>
                            <th>Name</th>
                            <th>Email</th>
                            <th>Location</th>
                            <th>Actions</th>
                        </tr>
                    </thead>
                    <tbody>
                            {tourists && tourists.map(u => <Row tourist={u} key={u.id} />)}
                   </tbody>
            </table>
        
    )
}

export default Touristtable


React component Touristtable is responsible for rendering a table of tourist data. The component imports necessary modules and styles. It imports React, the Form component from a file named "./Addtourist", and CSS styles for Bootstrap and Font Awesome icons.

Function Component: The Touristtable component is defined as a functional component taking in props tourists, postTourist, updateTourist, and deleteTourist. These props seem to be functions or data related to managing tourist information. Within the Touristtable component, there's a nested component called Row, which represents a single row in the table. It takes a prop named tourist which is an object containing data about a tourist.

Row Component: This component renders a table row (<tr>) for each tourist. It displays tourist information such as name, email, and location in separate cells (<td>). Additionally, it includes icons for editing and deleting a tourist entry. Clicking on the edit icon toggles the visibility of a form below the row.

Show Update User Function: This function toggles the visibility of the form for updating tourist information. It selects the form element by class name and toggles its visibility.

React component responsible for rendering a table of tourist data with the ability to edit and delete each entry. It separates the rendering logic into smaller, reusable components for better maintainability and readability.

Addtourist.js 


import React, { useState } from "react"
import 'font-awesome/css/font-awesome.min.css';
import { faL } from "@fortawesome/free-solid-svg-icons";


const Addtourist = ({ userData = {}, postUser, updateTourist,showUpdateUser }) => {
const [user, setUser] = useState({
        id: userData.id ?? 0,
        tourist_name: userData.tourist_name ?? "",
        tourist_email: userData.tourist_email ?? "",
        tourist_location: userData.tourist_location ?? "",
    })

const handleValue = e => {
        setUser({ ...user, [e.target.name]: e.target.value })
    }

const submitUser = e => {
        e.preventDefault()
        debugger;
if (user.tourist_name === "" || user.tourist_email === "" || user.tourist_location === "") return

if (userData.id) {
            debugger;
            updateTourist(userData.id, user)
        } else {
            postUser(user)
        }
        setUser({ ...user, "tourist_name": "", "tourist_email": "", "tourist_location": "" })
    }
const hiderow = e => {
        showUpdateUser(userData.id);
    }
const isAdd = !userData.id ? true : false;
return (
        <>
            <td>
                <input
                    type='text'
                    name='tourist_name'
                    className="form-control"
                    value={user.tourist_name}
                    placeholder='Name'
                    onChange={e => handleValue(e)}
                />
            </td>
            <td>
                <input
                    type='email'
                    name='tourist_email'
                    className="form-control"
                    value={user.tourist_email}
                    placeholder='Email'
                    onChange={e => handleValue(e)}
                />
            </td>
            <td>
                <input
                    type='text'
                    name='tourist_location'
                    className="form-control"
                    value={user.tourist_location}
                    placeholder='location..'
                    onChange={e => handleValue(e)}
                />
            </td>
            <td>
                {isAdd ?
                    <input
                        className='btn btn-primary btnsubmit'
                        type='submit'
                        value={`${!userData.id ? "Add new user" : "Save user"}`}
                        onClick={submitUser}
                    /> :
                    <i className="fa fa-check fa-2x text-success" onClick={submitUser}></i>
                }
                {isAdd ? "" : <i className="fa fa-times fa-2x text-muted" onClick={hiderow}></i>}
            </td>
        </>
    )
}

export default Addtourist


The Addtourist component is defined as a functional component.It accepts props such as userData, postUser, updateTourist, and showUpdateUser. These props are used for managing tourist data and interactions.

The component utilizes the useState hook to manage local state. It initializes a state variable user which holds the tourist data. If userData is provided (for editing an existing tourist), it initializes the state with that data; otherwise, it initializes with empty strings.

handleValue function updates the state when input values change.

submitUser function handles form submission. It prevents the default form submission behavior, performs some validation to ensure all required fields are filled, and then either calls postUser to add a new tourist or updateTourist to update an existing tourist.hiderow function is called when the user clicks on the cancel icon. It invokes the showUpdateUser function.

The component renders a form with input fields for tourist name, email, and location.The input fields are controlled components, meaning their values are controlled by the component's state (user).

Conditional rendering is used to determine whether to show an "Add new user" button or a "Save user" button based on whether userData.id exists .If editing an existing tourist, a cancel icon is shown alongside the "Save user" button.

Addtourist component provides a form for adding or editing tourist information, with input fields for name, email, and location. It handles form submission and includes functionality for canceling edits.

Crudtourists.js

import React, { useState, useEffect } from "react"
import Form from "./Addtourist"
import Tablelist from "./Touristtable"
import 'bootstrap/dist/css/bootstrap.min.css';

import { restHelper } from "../httphelpers/restHelper"

const Crudtourists = () => {
const [tourists, settourists] = useState(null)

const url = "http://samplerestapi.com/api/Tourist"
const api = restHelper()

    useEffect(() => {
        gettourists()
    }, [])

const postTourist = tourist => {
        api
            .postCreate(`${url}`, { body: tourist })
            .then(res => gettourists())
            .catch(err => console.log(err))
    }

const updateTourist = (id, tourist) => {
        api
            .putUpdate(`${url}/${id}`, { body: tourist })
            .then(res => gettourists())
            .catch(err => console.log(err))
    }

const deleteTourist = id => {
        api
            .deletedata(`${url}/${id}`, {})
            .then(res => gettourists())
            .catch(err => console.log(err))
    }

const gettourists = () => {
        api
            .get(`${url}`)
            .then(res => {
if(res && res.data)
                {
                    settourists(res.data)
                }
            })
            .catch(err => console.log(err))
    }
if (!tourists) return null

return (
        <>
            <h3>Add New Record</h3>
            <table>
                <tbody>
                    <tr>
                    <Form postUser={postTourist} />
                    </tr>
                </tbody>
            </table>
            
            <div className='container-fluid'>
                <h3>All Tourist</h3>
                <Tablelist
                    tourists={tourists}
                    settourists={settourists}
                    postTourist={postTourist}
                    updateTourist={updateTourist}
                    deleteTourist={deleteTourist}
                />
            </div>
        </>
    )
}

export default Crudtourists


Functions like postTourist, updateTourist, deleteTourist, and gettourists are defined to perform CRUD operations using an API. These functions make HTTP requests using restHelper to interact with the API endpoints.

Each CRUD operation updates the tourists state by fetching the latest data after the operation is completed.

Component user for managing tourist records, including fetching data, rendering a form for adding new records, and displaying a table of existing records with options for updating and deleting them. It encapsulates the CRUD functionality and separates concerns by using child components for form and table rendering.

App.js

import logo from './logo.svg';
import './App.css';
import CrudData from "./components/Crudtourists"
import 'bootstrap/dist/css/bootstrap.min.css';
function App() {
return (
    <div className="container-fluid">
      <main>
                <CrudData />
            </main>
    </div>
  );
}

export default App;

I’m assuming that you are familiar with React Js framework and creating React Js applications. If not then please go through the following articles: