使用State进行所需的验证

时间:2019-06-24 06:43:10

标签: javascript reactjs

我试图在对必填字段做出反应时手动实施表单验证。我想要的是用红色边框突出显示所有没有价值的表格。

当前,如果没有数据,我可以使其突出显示所有表单,但是只要我在表单上键入任何内容,数据仍会以红色突出显示。我真正想做的是\)

这是我目前正在做的事情

highlight the selected input with red border if there isn't any value and prevent the form from submitting.

Code for checking if there's a value in the textbox

isProfessionalFormValid(){ const { firstName, lastName, contactPhone, contactOfficePhone, address, city, companyName, newsletter_subscription} = this.state.formData; return firstName && lastName && contactPhone && contactOfficePhone && address && city && companyName && newsletter_subscription; } requiredFields(){ if(!this.isProfessionalFormValid()){ this.setState({ errorFirstName: 'error', errorLastName: 'error', errorAddress: 'error', errorCity: 'error', errorCompanyName: 'error', errorNewsletterSubscription: 'error', errorContactPhone: 'error', errorContactOfficePhone: 'error', errorMessage: '' }); return false; } return true; }

Some part of the form being rendered

我当前表格的输出 enter image description here

我的提交行为

<form id={"registration_form"} onSubmit={(e) => this.handleSubmit(e)} noValidate>
                <div class="PixelForm-title"> {t('form.registration.title.label')}</div>
                <div className='RegisterModal--line-wrapper'>
                    <div className={'line'} />
                </div>
                <div className="form-group PixelFormField">
                    <input
                        id={"firstName"}
                        placeholder={t('form.registration.first_name.label') + '*'}
                        className={"PixelForm-input" + " " + (this.state.errorFirstName === 'error' ? 'hasError' : '')}
                        type="text"
                        name={"firstName"}
                        required
                        onChange={(e) => this.handleChange(e)}
                        value={this.state.formData.firstName}
                    />
                </div>
                <div className="form-group PixelFormField">
                    <input
                        id={"lastName"}
                        placeholder={t('form.registration.last_name.label') + '*'}
                        className={"PixelForm-input" + " " + (this.state.errorLastName === 'error' ? 'hasError' : '')}
                        type="text"
                        name={"lastName"}
                        required
                        onChange={(e) => this.handleChange(e)}
                        value={this.state.formData.lastName}
                    />
                </div>

                <PhoneInput name={"contactPhone"}
                            onChange={(e) => this.handleChange(e)}
                            className={"PixelForm-input" + " " + (this.state.errorContactPhone === 'error' ? 'hasError' : '')}
                            placeholder={t('form.registration.mobile_phone.label') + '*'}
                />

                <PhoneInput name={"contactOfficePhone"}
                            onChange={(e) => this.handleChange(e)}
                            className={"PixelForm-input" + " " + (this.state.errorContactOfficePhone === 'error' ? 'hasError' : '')}
                            placeholder={t('form.registration.office_phone.label')}
                />
                <div className="PixelForm-subheader"> {t('agency_information')}</div>
                <div className='RegisterModal--line-wrapper'>
                    <div className={'line'} />
                </div>
                <div className="form-group PixelFormField">
                    <input
                        id={"companyName"}
                        placeholder={t('form.registration.broker_name.label') + '*'}
                        className={"PixelForm-input" + " " + (this.state.errorCompanyName === 'error' ? 'hasError' : '')}
                        type="text"
                        name={"companyName"}
                        required
                        onChange={(e) => this.handleChange(e)}
                        value={this.state.formData.companyName}
                    />
                </div>

                <div className="form-group PixelFormField">
                    <input
                        id={"address"}
                        placeholder={t('form.registration.broker_address.label') + '*'}
                        className={"PixelForm-input" + " " + (this.state.errorAddress === 'error' ? 'hasError' : '')}
                        type="text"
                        name={"address"}
                        required
                        onChange={(e) => this.handleChange(e)}
                        value={this.state.formData.address}
                    />
                </div>

                <div className="form-group PixelFormField">
                    <input
                        id={"city"}
                        placeholder={t('form.registration.broker_city.label') + '*'}
                        className={"PixelForm-input" + " " + (this.state.errorCity === 'error' ? 'hasError' : '')}
                        type="text"
                        name={"city"}
                        required
                        onChange={(e) => this.handleChange(e)}
                        value={this.state.formData.city}
                    />
                </div>

                {(this.state.errorMessage) ? (
                    <div class="PixelForm-error form-group">
                        {t(this.state.errorMessage)}
                    </div>) : ''}


            </form>

总结一下。我只想在提交表单时用红色边框突出显示那些没有值的输入。

3 个答案:

答案 0 :(得分:1)

很酷,所以我已经修改了您的组件,以按照您的期望集成表单验证和错误处理。请参阅此处的codeandbox进行操作:https://codesandbox.io/s/dreamy-mayer-2ck5z

请注意,我注释掉了您正在使用的PhoneInput组件,只是使用了普通的input标签作为临时选项。照原样,您应该能够无缝交换它。请记住应用您的样式。 :)

import React from "react";

class Form extends React.Component {
  state = {
    inputs: {
      firstName: "",
      lastName: "",
      companyName: "",
      address: "",
      contactPhone: "",
      contactOfficePhone: "",
      city: ""
    },
    errors: {
      firstName: false,
      lastName: false,
      companyName: false,
      address: false,
      contactPhone: false,
      contactOfficePhone: false,
      city: false
    }
  };

  handleOnChange = event => {
    const { name, value } = event.target;
    this.setState({
      ...this.state,
      inputs: {
        ...this.state.inputs,
        [name]: value
      },
      errors: {
        ...this.state.errors,
        [name]: false
      }
    });
  };

  handleOnBlur = event => {
    const { inputs } = this.state;
    if (inputs[event.target.name].length === 0) {
      this.setState(
        {
          errors: {
            ...this.state.errors,
            [event.target.name]: true
          }
        },
        () => console.log(this.state)
      );
    }
  };

  handleOnSubmit = event => {
    event.preventDefault();
    const { inputs } = this.state;
    //create new errors object
    let newErrorsObj = Object.entries(inputs)
      .filter(([key, value]) => {
        return value.length === 0;
      })
      .reduce((obj, [key, value]) => {
        if (value.length === 0) {
          obj[key] = true;
        } else {
          obj[key] = false;
        }
        return obj;
      }, {});

    if (Object.keys(newErrorsObj).length > 0) {
      this.setState(
        {
          errors: newErrorsObj
        },
        () => console.log(this.state)
      );
    } else {
      //submission was succcessful
      //do logic
      console.log("success!");
    }
  };
  render() {
    const { errors } = this.state;
    return (
      <form id="registration_form" onSubmit={this.handleOnSubmit} noValidate>
        <div class="PixelForm-title">Register</div>
        <div className="RegisterModal--line-wrapper">
          <div className={"line"} />
        </div>
        <div className="form-group PixelFormField">
          <input
            id={"firstName"}
            placeholder={"first name"}
            className={`PixelForm-input ${errors.firstName ? "hasError" : ""}`}
            type="text"
            name={"firstName"}
            required
            onChange={e => this.handleOnChange(e)}
            value={this.state.firstName}
          />
        </div>
        <div className="form-group PixelFormField">
          <input
            id={"lastName"}
            placeholder={"last name"}
            className={`PixelForm-input ${errors.lastName ? "hasError" : ""}`}
            type="text"
            name={"lastName"}
            required
            onChange={e => this.handleOnChange(e)}
            value={this.state.lastName}
          />
        </div>

        {/*
        going to use a regular input for now, but you can swap this
        */}
        {/* <PhoneInput
          name={"contactPhone"}
          onChange={e => this.handleChange(e)}
          className={
            "PixelForm-input" +
            " " +
            (this.state.errorContactPhone === "error" ? "hasError" : "")
          }
          placeholder={"form.registration.mobile_phone.label" + "*"}
        /> */}

        <input
          name="contactPhone"
          placeholder="contact phone"
          required
          className={`PixelForm-input ${errors.contactPhone ? "hasError" : ""}`}
          onChange={e => this.handleOnChange(e)}
          value={this.state.contactPhone}
        />

        {/*<PhoneInput
          name={"contactOfficePhone"}
          onChange={e => this.handleChange(e)}
          className={
            "PixelForm-input" +
            " " +
            (this.state.errorContactOfficePhone === "error" ? "hasError" : "")
          }
          placeholder={t("form.registration.office_phone.label")}
        />*/}
        <input
          name="contactOfficePhone"
          placeholder="contact office phone"
          required
          className={`PixelForm-input ${
            errors.contactOfficePhone ? "hasError" : ""
          }`}
          onChange={e => this.handleOnChange(e)}
          value={this.state.contactOfficePhone}
        />

        <div className="PixelForm-subheader"> {"agency_information"}</div>
        <div className="RegisterModal--line-wrapper">
          <div className={"line"} />
        </div>
        <div className="form-group PixelFormField">
          <input
            id={"companyName"}
            placeholder={"company"}
            className={`PixelForm-input ${
              errors.companyName ? "hasError" : ""
            }`}
            type="text"
            name={"companyName"}
            required
            onChange={e => this.handleOnChange(e)}
            value={this.state.companyName}
          />
        </div>

        <div className="form-group PixelFormField">
          <input
            id={"address"}
            placeholder={"address"}
            className={`PixelForm-input ${errors.address ? "hasError" : ""}`}
            type="text"
            name={"address"}
            required
            onChange={e => this.handleOnChange(e)}
            value={this.state.address}
          />
        </div>

        <div className="form-group PixelFormField">
          <input
            id={"city"}
            placeholder={"city"}
            className={`PixelForm-input ${errors.city ? "hasError" : ""}`}
            type="text"
            name={"city"}
            required
            onChange={e => this.handleOnChange(e)}
            value={this.state.city}
          />
        </div>

        {Object.values(errors).includes(true) ? (
          <div class="PixelForm-error form-group">
            You forgot to fill something out
          </div>
        ) : (
          ""
        )}
        <button type="submit">Submit</button>
      </form>
    );
  }
}

export default Form;

答案 1 :(得分:0)

您可能希望在用户单击“提交”按钮时(而不是在用户在每个字段中键入内容时)运行逻辑来检查输入字段的状态。

您可以使用e.preventDefault()More info here)阻止表单提交。

为此,您可以使用:

<form onSubmit={this.requiredFields}>

requiredFields(e){
    if(!this.isProfessionalFormValid()){
        e.preventDefault(); // << Prevent form submission
        this.setState({
            errorFirstName: 'error',
            errorLastName: 'error',
            errorAddress: 'error',
            errorCity: 'error',
            errorCompanyName: 'error',
            errorNewsletterSubscription: 'error',
            errorContactPhone: 'error',
            errorContactOfficePhone: 'error',
            errorMessage: ''
        });

        return false;
    }

    return true;
}

答案 2 :(得分:0)

您做错了。所有字段都必须为非空,然后才能生效。

    getFieldsThatHasError() {
      return this.state.formData.reduce((soFar, value, key) => {
        if (!value) {
          soFar[key] = 'error'
        }

        return soFar
      }, {})
    }

    requiredFields() {
      const errorFields = getFieldsThatHasError()

      this.setState({
        ...errorFields,
        errorMessage: ''
      })

      if (Object.keys(errorFields).length) {
        return false
      }

      return true
    }