I’m learning React and have created a two page application. The first presents the user with a list of customers from a database, with Add, Edit, Delete, View buttons, my ‘App.js’. The second presents a “dialog box” using a CustomerForm component, which is visible when one of four variables is set to true (isAdding, isEditing, isDeleting, isViewing).
CustomerForm.js presents fields from the Customer recor, as input boxes, and should allow the user to perform the appropriate operation on them. I’ve got as far as displaying the data when the user clicks edit, but the fields appear uneditable. The issue relates to the value
attribute below:
value={customer != null ? customer[field.name] : ""}
When I omit this, the text is editable, however the customer record is not shown. The full listing of App.css, CustomerForm.css and CustomerForm.js follow:
App.css:
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
button {
border: none; /* Remove the border */
border-radius: 0; /* Make the corners square (0 radius) */
box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.3); /* Shadow to the bottom-right */
padding: 5px 10px; /* vert, horiz. Add some padding */
background-color: darkgray; /* Button background color */
color: #FFFFFF; /* Button text color */
font-size: small; /* Font size */
cursor: pointer; /* Show a pointer cursor on hover */
outline: none; /* Remove the default outline on focus */
margin: 4px 4px; /* very, horiz. Add horizontal space between buttons */
}
h1 {
color: black;
font-weight: bold;
font-family: 'Verdana', 'Arial', 'Helvetica', sans-serif;
font-size: x-large;
}
th {
background-color: darkgray;
color: white;
font-weight: normal;
font-family: 'Verdana', 'Arial', 'Helvetica', sans-serif;
font-size: small; /* Font size */
margin: 0 4px; /* Add horizontal space between buttons */
text-align: left;
}
td {
/* background-color: lightgray;*/
font-family: 'Verdana', 'Arial', 'Helvetica', sans-serif;
font-size: small;
text-align: left;
}
.note {
color: black;
font-style: italic;
font-family: 'Verdana', 'Arial', 'Helvetica', sans-serif;
font-size: x-small;
}
.selectedCustomer {
background-color: blue; /* Color for the highlighted row */
color: white;
cursor: pointer;
}
.customer {
background-color: lightgray;
color: black;
cursor: pointer;
}
CustomerForm.css:
.modal-overlay { /* this is for a window-sized <div> that stops interaction with the items below it */
position: fixed; /* the overlay stays in place regardless of scrolling */
top: 0; /* top-left of overlay */
left: 0;
width: 100%; /* from top-left, this covers the entire window, no matter what is done to the window */
height: 100%;
background: rgba(0, 0, 0, 0.5); /* drop the visibility of everything behind by 50% */
display: flex; /* These flexbox properties center the modal dialog horizontally and vertically within the overlay. The combination of justify-content: center; and align-items: center; ensures that the .modal-content (the dialog) is always in the middle of the screen, providing a focused area for user interaction. */
justify-content: center;
align-items: center;
}
.modal-content {
background: white;
padding: 20px;
border-radius: 5px;
width: auto;
height: auto;
max-width: 500px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.buttonBar {
text-align: right;
}
.editableInput {
background-color: white;
}
.nonEditableInput {
background-color: lightBlue;
}
td {
padding-right: 10px; /* Adds padding to the right side of the cell */
}
CustomerForm.js:
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import FormModes from './FormModes';
import './CustomerForm.css'; // Include CSS for modal styling
const CustomerForm = ({ customer, mode, onClose }) =>
{
const [formData, setFormData] = useState((customer != null) ?
customer :
{
CustomerID: '',
CustomerName: '',
Address1: '',
Address2: '',
Address3: '',
Town: '',
Postcode: '',
Country: '',
PhoneNumber: '',
CustomerID: '',
});
const [formMode, setFormMode] = useState(mode);
const [error, setError] = useState(null);
const formFields = // array of fields to show
[
{label:'Customer Name', type:'text', name:'CustomerName'},
{label:'Address 1', type:'text', name:'Address1'},
{label:'Address 2', type:'text', name:'Address2'},
{label:'Address 3', type:'text', name:'Address3'},
{label:'Town', type:'text', name:'Town'},
{label:'Postcode', type:'text', name:'Postcode'},
{label:'Country', type:'text', name:'Country'},
{label:'Phone Number', type:'text', name:'PhoneNumber'},
];
const buttonText = () =>
{
switch (formMode)
{
case FormModes.Add: return "Add";
case FormModes.Edit: return "Update";
case FormModes.Delete: return "DELETE";
case FormModes.View: return "Close";
default: throw new Error("Unknown formMode: ${formMode}")
}
};
const isReadOnly = () =>
{
return ((formMode==FormModes.Delete) || (formMode==FormModes.View));
};
const handleSubmit = async (event) =>
{
try
{
event.preventDefault(); // this stops the default submit action
switch (formMode)
{
case FormModes.Add:
break;
case FormModes.Edit:
const response = await axios.post('/api/customers', formData);
break;
case FormModes.Delete:
break;
case FormModes.View:
break;
default:
throw new Error('Unknown form Mode ${formMode}.')
}
onClose();
} catch (err) {
setError(err.message);
}
};
return (
<div className="modal-overlay">
<div className="modal-content">
<h2>{formMode} Customer</h2>
<form onSubmit={handleSubmit}>
<table border="0">
{formFields.map((field) =>
<tr key={field.CustomerID}>
<td padding-right="10px"><label>{field.label}</label></td>
<td><input type={field.type}
name={field.name}
value={(customer != null) ? customer[field.name] : ""}
placeholder={field.label}
readOnly={isReadOnly()}
className={isReadOnly() ? "nonEditableInput" : "editableInput"}
/>
</td>
</tr>
)}
</table>
<div className="buttonBar">
<button type="submit">{buttonText()}</button>
<button type="button" onClick={onClose}>Cancel</button>
{error && <p>Error: {error}</p>}
</div>
</form>
</div>
</div>
);
};
export default CustomerForm;
My question is, why does including this line:
value={customer != null ? customer[field.name] : ""}
lock the input field to that value? I simply want to set it when the field is shown and be editable.