У меня есть этот state
, который представляет продукты.
const [rowsData, setRowsData] = useState([
{ width: "", height: "", quantity: "" },
]);
И это table
, который пользователь может добавить, сколько строк (товаров) по мере необходимости или удалить.
return (
<>
{rowsData.map((data, index) => {
const { width, height, quantity} = data;
return (
<tr key = {index}>
<td>{index + 1}</td>
<td>
<input
type = "number"
value = {width}
onChange = {(evnt) => handleChangeEvent(index, evnt)}
name = "width"
className = {wError ? "input input-error border-2 input-bordered w-full max-w-xs" : "input input-bordered w-full max-w-xs"}
/>
</td>
<td>
<input
type = "number"
value = {height}
onChange = {(evnt) => handleChangeEvent(index, evnt)}
name = "height"
className = {hError ? "input input-error border-2 input-bordered w-full max-w-xs" : "input input-bordered w-full max-w-xs"}
/>{" "}
</td>
<td>
<input
type = "number"
value = {quantity}
onChange = {(evnt) => handleChangeEvent(index, evnt)}
name = "quantity"
className = {qError ? "input input-error border-2 input-bordered w-full max-w-xs" : "input input-bordered w-full max-w-xs"}
/>{" "}
</td>
<td>
{index !==0 ? <button className = "btn" onClick = {() => deleteTableRows(index)}>
x
</button>: null}
</td>
</tr>
);
})}
Функция handlChange()
обнаруживает любые изменения в полях input
и запускает setState
.
const handleChangeEvent = (index, evnt) => {
const { name, value } = evnt.target;
const rowsInput = [...rowsData];
rowsInput[index][name] = value;
setRowsData(rowsInput);
};
Все поля должны принимать числа только на кнопке отправки, если пользователь вводит что-либо еще, вокруг поля ввода, содержащего ошибку, должна появиться красная рамка ошибки.
Мое решение проблемы было таким:
1- A сделал 3 ошибки usestats
для каждого поля (w->ширина, h->высота, q->количество)
const [wError, setWError] = useState(false);
const [hError, setHError] = useState(false);
const [qError, setQError] = useState(false);
2- Я проверил value
каждого поля ввода, является ли это числом или нет.
const createOrder = () => {
let wCheck, hCheck, qCheck
rowsData.map((e) => {
wCheck = !isNaN(e.width) && !isNaN(parseFloat(e.width));
hCheck = !isNaN(e.height) && !isNaN(parseFloat(e.height));
qCheck = !isNaN(e.quantity) && !isNaN(parseFloat(e.quantity));
});
};
3- Установите переменные ошибок (wError, hError, qError), чтобы они были противоположны проверочным переменным (wCheck, hCheck, qCheck).
setWError(!wCheck);
setHError(!hCheck);
setQError(!qCheck);
4- Я стилизую поле ввода на основе переменной ошибки (как показано в первом фрагменте).
className = {qError ? "input input-error border-2 input-bordered w-full max-w-xs" : "input input-bordered w-full max-w-xs"}
Решение Заключение
Это решение ужасно. В нем есть несколько ошибок, которые я не смог исправить
Как видите, ошибка основана только на последнем поле ввода. Таким образом, средство проверки ошибок помечает весь столбец как ошибку (3-й столбец), а иногда помечает весь столбец как действительный (1-й столбец).
Как изменить функцию, чтобы она нацеливалась на определенное поле ввода?
Вы можете добавить новое свойство в свой массив продуктов, в котором будет храниться сообщение об ошибке, или даже логическое значение, которое будет true
, когда ввод имеет некоторую ошибку проверки. В вашей функции handleChangeEvent()
вы можете проверить, является ли значение недопустимым, и установить это поле. В цикле вы проверяете поле и, если есть ошибка, устанавливаете красную границу для ввода текущей итерации.
Не забудьте обновить массив с помощью оператора распространения, чтобы обеспечить запуск повторного рендеринга.
Пример ниже:
export function App(props) {
const [rows, setRows] = useState([
{value: '', error: false},
{value: '', error: false},
{value: '', error: false},
])
function handleChangeEvent(evt, index) {
let value = evt.target.value
rows[index].value = value
rows[index].error = !isNaN(value) && !isNaN(parseFloat(value))
setRows([...rows])
}
return (
<div className='App'>
<table>
<tbody>
{rows.map((row, index) => (
<tr key = {index}>
<input
style = {{'border': row.error ? '1px solid red' : ''}}
value = {row.value}
onChange = {(evt) => handleChangeEvent(evt, index)}
placeholder = "Enter value"
/>
</tr>
))}
</tbody>
</table>
</div>
);
}
Чтобы проверить, есть ли у какого-либо ввода ошибка для отключения операции отправки, вы можете проверить, является ли какое-либо поле error
true
. Если нет ни одной с true
, форма действительна.