I have a table of text boxes and want a given text box to highlight when I change it. I have the CSS class but am not able to apply it to a specific field. Currently the setChanged() makes the entire table highlighted. I should be able to focus it to a given field given that I have access to the ID and the field name within the event handler righ?
function AppCookie() {
const [cookies, setCookies] = useState();
const [changed, setChanged] = useState('');
const onChangeInput = (e, id) => {
const { name, value } = e.target
setChanged('highlighted-input')
const editData = cookies.map((cookie) =>
cookie.id === id && name ? { ...cookie, [name]: value } : cookie
)
editData[id-1].name
setCookies(editData)
}
const handleClick = async (event) => {
...}
useEffect(() => {
populateCookieData();
}, []);
const contents = cookies === undefined
? <p><em>Loading...</em></p>
:
<table className="table table-striped" aria-labelledby="tabelLabel">
<thead>
<tr>
<th>Id</th>
<th>Date</th>
<th>Name</th>
<th>Desc</th>
<th>Price</th>
</tr>
</thead>
<tbody>
{cookies.map(cookie =>
<tr key={cookie.id}>
<td>{cookie.id}</td>
<td>{cookie.date}</td>
<td>
<input
name="name"
value={cookie.name}
type="text"
onChange={(e) => onChangeInput(e,
cookie.id)}
placeholder="Type Name"
className={changed} />
</td>
<td><input
name="desc"
value={cookie.desc}
type="text"
onChange={(e) => onChangeInput(e, cookie.id)}
placeholder="Type Desc"
/></td>
<td><input
name="price"
value={cookie.price}
type="text"
onChange={(e) => onChangeInput(e, cookie.id)}
placeholder="Type Price"
className={changed}/></td>
<td> <button type="submit" onClick={() => handleClick({cookie})}>Update</button></td>
</tr>
)}
</tbody>
</table>;
return (
<div>
<h1 id="tabelLabel">Cookies</h1>
{contents}
</div>
);
async function populateCookieData() {
...
}
}
I do not see all your code, but do you use the useState
hook:
const [changed, setChanged] = useState('');
in the same component where you do cookies.map
?
The state created by useState
hook is used for the whole component where you call this hook. You store just "highlighted-input"
string there, and the changed
variable is visible and is absolutely the same for every cookie
in your cookies.map
cycle.
In order to highlight a specific input, you must save which one to highlight. And at the moment of the loop where you display the inputs, check if the current one is highlighted.
I have prepared a code sample that highlights the last edited input. For this purpose, when changing an input in the onChangeInput handler, I use setState to store the ID of the changed cookie.
const cookies = [
{ id: "lang", desc: "en" },
{ id: "theme", desc: "dark" },
];
const highlighted = "highlighted-input";
function CookiesTable() {
// create the initial state with empty string
const [lastChangedId, setLastChangedId] = React.useState("");
const onChangeInput = (e, id) => {
const { name, value } = e.target;
// write the id of changed cookie to the lastChangedId state
setLastChangedId(id);
};
return (
<table>
{cookies.map((cookie) => (
<tr key={cookie.id}>
<td>{cookie.id}</td>
<td>
<input
name="desc"
defaultValue={cookie.desc}
type="text"
onChange={(e) => onChangeInput(e, cookie.id)}
placeholder="Type Desc"
className={lastChangedId === cookie.id ? highlighted : ""}
/>
</td>
</tr>
))}
</table>
);
}
const rootElement = document.getElementById("root");
const root = ReactDOM.createRoot(rootElement);
root.render(<CookiesTable />);
.highlighted-input {
background-color: aqua;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
If you want, for example, to highlight not only the last but all changed inputs, it is better to store an object in the state:
// Create the initial state with empty object
const [changed, setChanged] = useState({});
const onChangeInput = (e, id) => {
const { name, value } = e.target;
// add a new property with current cookie id when input is chagned
setChanged((allChanged) => ({
...allChanged,
[id]: true,
}));
};
// ... all other code ...
// check, if current cookie.id is presented in the "changed" state
className={changed[cookie.id] ? "highlighted-input" : ""}