【问题标题】:How to add red borders around any invalid input index in mapped inputs如何在映射输入中的任何无效输入索引周围添加红色边框
【发布时间】:2021-03-17 01:52:02
【问题描述】:

我有一个模式,它将对象 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>

ModalInput 定义在styles.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
}

如何确保如果用户为任何映射行输入了错误的输入,那么只有该特定输入而不是其他输入会显示红色边框?

【问题讨论】:

  • 我更新了我的答案,考虑看看并提供一些反馈!问候
  • 你能通过循环传递id吗?可能吗? newCompanies 对象的结构是什么。最好和最简单的方法是将带有错误状态的 id 存储在 state 中,并根据错误值和 id 将 props 传递给styled-component 进行比较。以下答案令人困惑。

标签: javascript css reactjs


【解决方案1】:

我认为最好的方法是添加一个 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;
}

【讨论】:

  • 这会在用户输入时检查输入吗?
  • @user2555 不,它不会。如果用户曾经键入,则该输入上的错误将被清除。它目前仅在用户尝试提交表单时检查有效性并设置错误。如果您希望始终在用户键入时检查有效性,请将其添加到输入的 onChange 回调中。
【解决方案2】:

你可以试试这样的:

定义您将需要的状态变量,我为输入值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() 函数中,每次输入值更改(组件重新渲染)时,我都会检查输入字段是否正确填写。根据这一点,我将类名更改为想要的值。我在这个例子中使用了引导类(border-danger、border-success),但如果你愿意,你可以用你自己的样式来做到这一点。

如果您只想在按钮onClick() 上进行验证,这也是可能的。

codesandbox link

【讨论】:

    猜你喜欢
    • 2019-03-17
    • 1970-01-01
    • 2020-11-06
    • 2014-04-24
    • 1970-01-01
    • 2021-08-28
    • 2020-07-11
    • 1970-01-01
    • 2015-04-13
    相关资源
    最近更新 更多