In this article, we are going to learn “how to build an editable table in Reactjs".
Demo App
This is the result you can play with.
Name | Position | |
---|---|---|
Many web apps nowadays are implementing tables with editable text fields. It enhances the user experience. Building editable text fields might seem arduous, but it becomes easy with the tricks. There are many ways to create them, but I’ll share the easiest one so you can do it without getting exhausted. So, let us get started.
Creating the Editable Text field in Table
Step 01: Create Table
In the first step, create a simple table like we do with plain HTML5
. A simple table is created to make the base for the editable text fields. After building the table, we will turn the Table Data: td
into an editable text
.
function EditableTable() {return (<div><table><thead><tr><th>Name</th><th>Email</th><th>Position</th></tr></thead><tbody><tr><td>John Doe</td><td>Frontend Developer</td></tr><tr><td>Sara</td><td>HR Executive</td></tr><tr><td>Mike</td><td>Backend Developer Developer</td></tr></tbody></table></div>)}export default EditableTable
Now we have to figure out how to turn this td: table data
into editable field
.
The first thing that came into mind is to wrap input
inside td
.
Let’s make the code clean
Before moving to Editable Text Field
let’s make this component a bit cleaner.
In real-world apps, we get data via APIs
. So to mock it, we will build an array of objects.
import { useState } from 'react'const data = [{id: '01',name: 'John Doe',position: 'Frontend Developer',},{id: '02',name: 'Sara',position: 'HR Executive',},{id: '03',name: 'Mike',position: 'Backend Developer',},]const EditableTable = () => {const [employeeData, setEmployeeData] = useState(data)return (<div><table><thead><tr><th>Name</th><th>Email</th><th>Position</th></tr></thead><tbody>{employeeData.map(({ id, name, email, position }) => (<tr key={id}><td>{name}</td><td>{email}</td><td>{position}</td></tr>))}</tbody></table></div>)}export default EditableTable
Step 02: Editable Table Data
The primary option that comes to mind for making editable table data
is wrapping the td
tag into the input
tag. Let us do this first.
<tbody>{employeeData.map(({ employeeId, name, email, position }) => (<tr key={employeeId}><td><inputname="name"value={name}type="text"onChange={onChangeInput}placeholder="Type Name"/></td><td><inputname="email"value={email}type="text"onChange={onChangeInput}placeholder="Type Email"/></td><td><inputname="position"type="text"value={position}onChange={onChangeInput}placeholder="Type Position"/></td></tr>))}</tbody>
But here is one problem…
Now observe that the editable text field is not yet functional. In the next step, we will make it functional.
Step 03: Changing Table data Value
We have to write an onChange Handler Function
for changing the table data value. This function is to handle the Input tag.
import { useState } from 'react'import './index.css'const data = [{employeeId: '01',name: 'John Doe',position: 'Frontend Developer',},{employeeId: '02',name: 'Sara',position: 'HR Executive',},{employeeId: '03',name: 'Mike',position: 'Backend Developer',},]const EditableTable = () => {const [employeeData, setEmployeeData] = useState(data)const onChangeInput = (e, employeeId) => {const { name, value } = e.targetconsole.log('name', name)console.log('value', value)console.log('employeeId', employeeId)const editData = employeeData.map((item) =>item.employeeId === employeeId && name ? { ...item, [name]: value } : item)console.log('editData', editData)setEmployeeData(editData)}return (<div className="container"><h1 className="title">ReactJS Editable Table</h1><table><thead><tr><th>Name</th><th>Email</th><th>Position</th></tr></thead><tbody>{employeeData.map(({ employeeId, name, email, position }) => (<tr key={employeeId}><td><inputname="name"value={name}type="text"onChange={(e) => onChangeInput(e, employeeId)}placeholder="Type Name"/></td><td><inputname="email"value={email}type="text"onChange={(e) => onChangeInput(e, employeeId)}placeholder="Type Email"/></td><td><inputname="position"type="text"value={position}onChange={(e) => onChangeInput(e, employeeId)}placeholder="Type Position"/></td></tr>))}</tbody></table></div>)}export default EditableTable
Now the main part,
const onChangeInput = (e, employeeId) => {const { name, value } = e.targetconsole.log('name', name)console.log('value', value)console.log('employeeId', employeeId)const editData = employeeData.map((item) =>item.employeeId === employeeId && name ? { ...item, [name]: value } : item)console.log('editData', editData)setEmployeeData(editData)}
You can see we have multiple consoles
in this function, to debug that are we getting correct values.
Then we map over employeeData
and check if the current employeeId
equals to the id
, and name
also matches with name
of input
, we will change only that input
values, the rest of the values will be the same.
To complete, we will setState
and pass editData
to it.
Read More On This
The article "How to Update an Array of Objects" will provide valuable insights on how to effectively update objects within an array.
It is a helpful resource to enhance your understanding of this topic.
Congrats, you have created the table with editable text fields.
What about making it stylish and interactive?
Styling the Editable Text fields in the Table
For interactivity, I added the hover
effect, on a text field, so user can know he can interact with it.
We also removed the default border
and styled input focus
state, to make the user experience smooth.
Complete Code
import { useState } from 'react'import './index.css'const data = [{employeeId: '01',name: 'John Doe',position: 'Frontend Developer',},{employeeId: '02',name: 'Sara',position: 'HR Executive',},{employeeId: '03',name: 'Mike',position: 'Backend Developer',},]const EditableTable = () => {const [employeeData, setEmployeeData] = useState(data)const onChangeInput = (e, employeeId) => {const { name, value } = e.targetconst editData = employeeData.map((item) =>item.employeeId === employeeId && name ? { ...item, [name]: value } : item)setEmployeeData(editData)}return (<div className="container"><h1 className="title">ReactJS Editable Table</h1><table><thead><tr><th>Name</th><th>Email</th><th>Position</th></tr></thead><tbody>{employeeData.map(({ employeeId, name, email, position }) => (<tr key={employeeId}><td><inputname="name"value={name}type="text"onChange={(e) => onChangeInput(e, employeeId)}placeholder="Type Name"/></td><td><inputname="email"value={email}type="text"onChange={(e) => onChangeInput(e, employeeId)}placeholder="Type Email"/></td><td><inputname="position"type="text"value={position}onChange={(e) => onChangeInput(e, employeeId)}placeholder="Type Position"/></td></tr>))}</tbody></table></div>)}export default EditableTable
CSS
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;600&display=swap');body {box-sizing: border-box;color: #220f5f;font-family: 'Poppins', sans-serif;}.container {width: 100%;max-width: 800px;padding: 0 10px;margin: 0 auto;margin-top: 70px;}.title {text-align: center;font-size: 26px;margin-bottom: 30px;}table {border-collapse: collapse;width: 100%;}tr th {font-size: 18px;padding: 12px;border: 1px solid #eeeeee;text-align: left;background-color: rgba(217, 221, 146, 0.2);}tr td {border: 1px solid #eeeeee;text-align: left;}input {font-size: 16px;background-color: transparent;border: none;width: 91%;padding: 12px 12px;font-family: 'Poppins', sans-serif;}input:hover {background-color: #fffaf3;}input:focus {outline: 1px solid #ccc;border: 1px solid #ccc;}