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.
We are using free rest API for showing the demo
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.
npx create-react-app crud-app
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.
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.
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,
}
}
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
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.
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: