使用 React 创建的输入字段不可编辑

问题描述 投票:0回答:1

我正在学习 React 并创建了一个两页应用程序。第一个向用户展示数据库中的客户列表,其中包含“添加”、“编辑”、“删除”、“查看”按钮,即我的“App.js”。第二个展示了一个使用 CustomerForm 组件的“对话框”,当四个变量之一设置为 true(isAdding、isEditing、isDeleting、isViewing)时,该对话框可见。

CustomerForm.js 将客户记录中的字段显示为输入框,并应允许用户对它们执行适当的操作。当用户单击编辑时,我已经显示了数据,但字段显示为不可编辑。该问题与以下

value
属性相关:

value={customer != null ? customer[field.name] : ""}

当我省略此选项时,文本是可编辑的,但不会显示客户记录。 App.css、CustomerForm.css 和 CustomerForm.js 的完整列表如下:

应用程序.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;

我的问题是,为什么要包括这一行:

value={customer != null ? customer[field.name] : ""}

将输入字段锁定为该值?我只是想在显示字段时设置它并且可以编辑。

javascript html css reactjs input
1个回答
0
投票

您已通过以编程方式设置

value
创建了“受控组件”。这可以防止浏览器更改该值。您要么需要添加一个
onChange
属性,并带有一个处理程序来更新
value
属性上设置的值,要么需要删除
value
属性。

请参阅 React 文档中的 input 中的

“我的文本输入在输入时不会更新”

© www.soinside.com 2019 - 2024. All rights reserved.