Reactjs - 表单输入验证

时间:2016-12-23 07:00:00

标签: javascript node.js reactjs forms validation

我的联系页面表格如下,

<form name="contactform" onSubmit={this.contactSubmit.bind(this)}>
  <div className="col-md-6">
    <fieldset>
      <input ref="name" type="text" size="30" placeholder="Name"/>
      <br/>
      <input refs="email" type="text" size="30" placeholder="Email"/>
      <br/>
      <input refs="phone" type="text" size="30" placeholder="Phone"/>
      <br/>
      <input refs="address" type="text" size="30" placeholder="Address"/>
      <br/>
    </fieldset>
  </div>
  <div className="col-md-6">
    <fieldset>
      <textarea refs="message" cols="40" rows="20"
                className="comments" placeholder="Message"/>
    </fieldset>
  </div>
  <div className="col-md-12">
    <fieldset>
      <button className="btn btn-lg pro" id="submit"
              value="Submit">Send Message</button>
    </fieldset>
  </div>
</form>

需要为所有字段添加验证。任何人都可以帮助我以这种反应形式添加验证吗?

10 个答案:

答案 0 :(得分:58)

您应该避免使用引用,您可以使用onChange函数执行此操作。

在每次更改时,更新已更改字段的状态。

然后,您可以轻松检查该字段是否为空或者您想要的其他内容。

您可以执行以下操作:

class Test extends React.Component {
    constructor(props){
       super(props);

       this.state = {
           fields: {},
           errors: {}
       }
    }

    handleValidation(){
        let fields = this.state.fields;
        let errors = {};
        let formIsValid = true;

        //Name
        if(!fields["name"]){
           formIsValid = false;
           errors["name"] = "Cannot be empty";
        }

        if(typeof fields["name"] !== "undefined"){
           if(!fields["name"].match(/^[a-zA-Z]+$/)){
              formIsValid = false;
              errors["name"] = "Only letters";
           }        
        }

        //Email
        if(!fields["email"]){
           formIsValid = false;
           errors["email"] = "Cannot be empty";
        }

        if(typeof fields["email"] !== "undefined"){
           let lastAtPos = fields["email"].lastIndexOf('@');
           let lastDotPos = fields["email"].lastIndexOf('.');

           if (!(lastAtPos < lastDotPos && lastAtPos > 0 && fields["email"].indexOf('@@') == -1 && lastDotPos > 2 && (fields["email"].length - lastDotPos) > 2)) {
              formIsValid = false;
              errors["email"] = "Email is not valid";
            }
       }  

       this.setState({errors: errors});
       return formIsValid;
   }

   contactSubmit(e){
        e.preventDefault();

        if(this.handleValidation()){
           alert("Form submitted");
        }else{
           alert("Form has errors.")
        }

    }

    handleChange(field, e){         
        let fields = this.state.fields;
        fields[field] = e.target.value;        
        this.setState({fields});
    }

    render(){
        return (
            <div>           
               <form name="contactform" className="contactform" onSubmit= {this.contactSubmit.bind(this)}>
                    <div className="col-md-6">
                      <fieldset>
                           <input ref="name" type="text" size="30" placeholder="Name" onChange={this.handleChange.bind(this, "name")} value={this.state.fields["name"]}/>
                           <span style={{color: "red"}}>{this.state.errors["name"]}</span>
                          <br/>
                         <input refs="email" type="text" size="30" placeholder="Email" onChange={this.handleChange.bind(this, "email")} value={this.state.fields["email"]}/>
                         <span style={{color: "red"}}>{this.state.errors["email"]}</span>
                         <br/>
                         <input refs="phone" type="text" size="30" placeholder="Phone" onChange={this.handleChange.bind(this, "phone")} value={this.state.fields["phone"]}/>
                         <br/>
                         <input refs="address" type="text" size="30" placeholder="Address" onChange={this.handleChange.bind(this, "address")} value={this.state.fields["address"]}/>
                         <br/>
                     </fieldset>
                  </div>

              </form>
            </div>
      )
    }
}

React.render(<Test />, document.getElementById('container'));

在这个例子中,我只对电子邮件和名称进行了验证,但您知道如何进行验证。其余的你可以自己做。

可能有更好的方法,但你会明白这一点。

Here is fiddle.

希望这有帮助。

答案 1 :(得分:5)

我已采用您的代码并使用库react-form-with-constraints对其进行了调整:https://codepen.io/tkrotoff/pen/LLraZp

const {
  FormWithConstraints,
  FieldFeedbacks,
  FieldFeedback
} = ReactFormWithConstraints;

class Form extends React.Component {
  handleChange = e => {
    this.form.validateFields(e.target);
  }

  contactSubmit = e => {
    e.preventDefault();

    this.form.validateFields();

    if (!this.form.isValid()) {
      console.log('form is invalid: do not submit');
    } else {
      console.log('form is valid: submit');
    }
  }

  render() {
    return (
      <FormWithConstraints
        ref={form => this.form = form}
        onSubmit={this.contactSubmit}
        noValidate>

        <div className="col-md-6">
          <input name="name" size="30" placeholder="Name"
                 required onChange={this.handleChange}
                 className="form-control" />
          <FieldFeedbacks for="name">
            <FieldFeedback when="*" />
          </FieldFeedbacks>

          <input type="email" name="email" size="30" placeholder="Email"
                 required onChange={this.handleChange}
                 className="form-control" />
          <FieldFeedbacks for="email">
            <FieldFeedback when="*" />
          </FieldFeedbacks>

          <input name="phone" size="30" placeholder="Phone"
                 required onChange={this.handleChange}
                 className="form-control" />
          <FieldFeedbacks for="phone">
            <FieldFeedback when="*" />
          </FieldFeedbacks>

          <input name="address" size="30" placeholder="Address"
                 required onChange={this.handleChange}
                 className="form-control" />
          <FieldFeedbacks for="address">
            <FieldFeedback when="*" />
          </FieldFeedbacks>
        </div>

        <div className="col-md-6">
          <textarea name="comments" cols="40" rows="20" placeholder="Message"
                    required minLength={5} maxLength={50}
                    onChange={this.handleChange}
                    className="form-control" />
          <FieldFeedbacks for="comments">
            <FieldFeedback when="*" />
          </FieldFeedbacks>
        </div>

        <div className="col-md-12">
          <button className="btn btn-lg btn-primary">Send Message</button>
        </div>
      </FormWithConstraints>
    );
  }
}

截图:

form validation screenshot

这是一个快速的黑客攻击。要获得正确的演示,请检查https://github.com/tkrotoff/react-form-with-constraints#examples

答案 2 :(得分:2)

interface AppComponent {
    @Component.Builder
    interface Builder {
        @BindsInstance
        fun application(app: Application): Builder

        fun build(): AppComponent
    }

    fun inject(app: App)
}

@Module(
        includes = [
            RetroiftModule::class,
            RegistrationModule::class,
            ScreenModule::class
        ]
)
class AppModule {
    @Provides
    fun context(app: Application) = app.applicationContext!!

    @Provides
    fun sharedPreferences(app: Application) = app.getPreferences()

答案 3 :(得分:1)

可能要迟到才能回答 - 如果您不想修改当前代码并且仍然可以在整个项目中使用类似的验证代码,那么您也可以尝试使用此代码 -  https://github.com/vishalvisd/react-validator

答案 4 :(得分:1)

更清洁的方法是使用joi-browser软件包。在这种状态下,您应该有一个错误对象,该对象包含表单中的所有错误。最初应将其设置为空对象。 创建架构;

import Joi from "joi-browser";
schema = {
    username: Joi.string()
      .required()
      .label("Username")
      .email(),
    password: Joi.string()
      .required()
      .label("Password")
      .min(8)
      .regex(/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9]).{8,1024}$/) //special/number/capital
   };

然后使用架构验证表单:

validate = () => {
    const options = { abortEarly: false };
    const result = Joi.validate(this.state.data, this.schema, options);
    console.log(data) // always analyze your data
    if (!result.error) return null; 
    const errors = {};
    for (let item of result.error.details) errors[item.path[0]] = item.message; //in details array, there are 2 properties,path and message.path is the name of the input, message is the error message for that input.
    return errors;
  };

在提交表单之前,请检查表单:

handleSubmit = e => {
    e.preventDefault();
    const errors = this.validate(); //will return an object
    console.log(errors);
    this.setState({ errors: errors || {} }); //in line 9 if we return {}, we dont need {} here
    if (errors) return;
    //so we dont need to call the server
    alert("success");
    //if there is no error call the server
    this.dosubmit();
  };

答案 5 :(得分:0)

使用React Hook,表单变得超级简单(React Hook表单:https://github.com/bluebill1049/react-hook-form

我已经重新使用了您的html标记。

这是一个codesandbox的工作版本:https://codesandbox.io/s/rmnyqm685o

import React from "react";
import useForm from 'react-hook-form';

function Test() {
  const { useForm, register } = useForm();
  const contactSubmit = data => {
    console.log(data);
  };

  return (
    <form name="contactform" onSubmit={contactSubmit}>
      <div className="col-md-6">
        <fieldset>
          <input name="name" type="text" size="30" placeholder="Name" ref={register} />
          <br />
          <input name="email" type="text" size="30" placeholder="Email" ref={register} />
          <br />
          <input name="phone" type="text" size="30" placeholder="Phone" ref={register} />
          <br />
          <input name="address" type="text" size="30" placeholder="Address" ref={register} />
          <br />
        </fieldset>
      </div>
      <div className="col-md-6">
        <fieldset>
          <textarea name="message" cols="40" rows="20" className="comments" placeholder="Message" ref={register} />
        </fieldset>
      </div>
      <div className="col-md-12">
        <fieldset>
          <button className="btn btn-lg pro" id="submit" value="Submit">
            Send Message
          </button>
        </fieldset>
      </div>
    </form>
  );
}

答案 6 :(得分:0)

我们有很多选择来验证react js表单。也许npm软件包有一些自身的局限性。根据您的需求,您可以选择正确的验证程序包。我想推荐一些,下面列出。

如果有人知道比这更好的解决方案,请将其放在评论部分以供其他人参考。

答案 7 :(得分:0)

尝试powerform-react。它基于powerform,这是一个超级可移植的Javascript表单库。一旦学习,就可以在任何框架中使用。即使使用香草Javascript也可以使用。

Checkout this simple form使用powerform-react

还有一个complex example

答案 8 :(得分:0)

例如,尝试一下 输入标签下方的必填属性将确保姓名字段应为空。

<input type="text" placeholder="Your Name" required />

答案 9 :(得分:0)

假设您了解 react useState Hook,如果您的表单很简单,您可以使用 state 变量来保存每个输入字段的值。然后在每个输入字段上添加 onChange 处理函数,这将更新状态变量。最后,您可以检查存储在状态变量中的值,以确保所有输入字段都有某个值。这是一个简单的例子。

import { useState } from "react";

export default function App() {
  const [name, setName] = useState("");
  const [email, setEmail] = useState("");
  const onChangeHandler = (fieldName, value)=>{
    if(fieldName === "name"){
      setName(value);
    }
    else if(fieldName==="email"){
      setEmail(value);
    }
  }
  const onSubmitHandler = (e)=>{
    e.preventDefault();
    if(name.trim()==="" || email.trim() ==""){
      alert("required both field");
    }
    else{
      alert(name+" " +email);
      setName("");
      setEmail("");
    }
  }
  return (
    <div className="App">
      <form onSubmit={(e)=>{onSubmitHandler(e)}}>
        <input type="text" value={name} onChange={(e)=>{ onChangeHandler("name",e.target.value)}} /> <br/>
         <input type="email"  value={email} onChange={(e)=>{ onChangeHandler("email",e.target.value)}} /> <br/>
         <input type="submit" value="Submit" />
        </form>
    </div>
  );
}

但是,如果您有一个复杂的表单,很难将每个值保存在状态变量中,然后在每个字段上使用验证。对于复杂的表单,建议使用 Formik 为您做所有事情,您可以使用 Yup 验证包,它也受 Formik 支持,它允许您添加更多简单的验证。