如何在映射的输入中为无效的输入索引添加红色边框



我有一个模态,将对象newCompanies的每个元素映射到一行:

{newCompanies.map((company, index) => {
return (
<div>
<div
className="side-by-side"
>
<ModalInput
type="text"
id="name"
value={company.name}
onChange={(e) =>
this.editCompanyArr(index, "name", e, "validName")
}
></ModalInput>
<ModalInput
type="text"
id="website"
value={company.website}
onChange={(e) =>
this.editCompanyArr(
index,
"website",
e,
"validWebsite"
)
}
></ModalInput>
<ModalInput
type="text"
id="sector"
value={company.class}
onChange={(e) =>
this.editCompanyArr(
index,
"sector",
e,
"validSector"
)
}
></ModalInput>

ModalInputstyles.js中定义:

export const ModalInput = styled.input`
padding: 10px;
margin: 10px 0;
border: 1px solid #f5f6f9;
border-radius: 20px;
background-color: #f5f6f9;
height: 100%;
width: ${props => props.width || 'auto'};
`;

这个函数检查用户是否输入了正确的值。例如,如果名称包含数字,则validName的值将变为false:

editCompanyArr(i, obj, e, stateObject) {
const { newCompanies, validName } = this.state;
if (e.target.value.match("^[a-zA-Z ]*$") != null) {
this.setState({ [stateObject]: true });
} else {
this.setState({ [stateObject]: false });
}
//edited out more body to update value in newCompanies
}

如果用户为任何映射行输入了不正确的输入,我如何确保只有该特定输入而不是其他输入获得红色边框?

我认为最好的方法是添加一个CSS类,将给他们你想要的轮廓。为状态中的每个输入保留一个标志,如果其值无效,则在提交时将其设置为true。然后,当用户单击输入或键入时,可以清除错误。

JSX:

const App = () => {
const [inputError, setInputError] = useState(false)
const refs = {
exampleInput: null
}
return (
<form onSubmit={e => {
const exampleInput = this.refs.exampleInput
const exampleInputVal = exampleInput.value
if(exampleInputVal) {
// It's valid! Submit it
} else {
// INVALID! Set error state: 
setInputError(true)
}
}}>
<input 
className={inputError ? 'error' : ''} 
ref={el => { refs.exampleInput = el }}
onChange={e => setInputError(false)}
onFocus{e => setInputError(false)}
/>
</form>
)
}

CSS:

input.error, 
input:focus.error {
outline: none;
box-shadow: 0 0 0 1px red;
}

你可以尝试这样做:

定义您需要的状态变量,我为输入值nameage创建了一个状态变量(作为示例)。我还定义了类的状态,这样当这个值改变时,组件就会重新呈现,边框颜色也会更新。

我设置了一些初始的className值,这样第一次渲染是带有红色边框的(在Bootstrap中border-danger)。

// initial classes
const initialClassNames = {
name: "border-danger",
age: "border-danger",
};
// needed states
const [classNames, setClassNames] = useState(initialClassNames);
const [values, setValues] = useState({ name: "", age: 0 });

然后我给不同的字段分配了它们自己的规范,我想稍后映射它们。请注意状态值是如何绑定到输入字段规范的。

// specs for all input fields
const inputFields = [
{
inputLabel: "Name", // label for the input field
inputName: "name", // name
inputValue: values.name, // value
inputClassName: classNames.name // className
},
{
inputLabel: "Age",
inputName: "age",
inputValue: values.age,
inputClassName: classNames.age
}
];

return()中,我映射所有字段并提供所需的JSX。

return (
<div className="container mt-3">
{inputFields.map((f, i) => {
return (
<div className="mb-5" key={i}>
<label htmlFor={`${f.inputName}${i}`}>{f.inputLabel}</label>
<input
id={`${f.inputName}${i}`}
name={f.inputName}
value={f.inputValue}
onChange={handleChange}
className={`form-control ${f.inputClassName}`}
></input>
</div>
);
})}
</div>
);

这是你想要如何处理你的输入的变化事件:

// handleChange for inputs
const handleChange = (e) => {
e.preventDefault();
setValues({
...values,
[e.target.name]: e.target.value
});
};

你可以做这样的验证:

useEffect(() => {
// validate name
if (values.name) {
setClassNames((prevState) => {
return { ...prevState, name: (prevState.name = "border-success") };
});
} else {
setClassNames((prevState) => {
return { ...prevState, name: (prevState.name = "border-danger") };
});
}
// validate age
if (parseInt(values.age, 10)) {
setClassNames((prevState) => {
return { ...prevState, age: (prevState.age = "border-success") };
});
} else {
setClassNames((prevState) => {
return { ...prevState, age: (prevState.age = "border-danger") };
});
}
}, [values.name, values.age]);

useEffect()函数中,我检查每次输入值更改(组件重新呈现)时输入字段是否正确填充。根据这一点,我将类名更改为所需的值。我在这个例子中使用了bootstrap类(border-danger, border-success),但是如果你愿意,你也可以用你自己的样式来做。

如果您只希望验证发生在例如按钮onClick()上,这也是可能的。

codesandbox联系