19

我正在使用官方Semantic UI React组件来创建 Web 应用程序。我的注册页面上有一个表单,其中包含一个电子邮件字段、一个密码字段和一个确认密码字段。

import {Component} from 'react';
import {Button, Form, Message} from 'semantic-ui-react';
import {signUp} from '../../actions/auth';

class SignUp extends Component {
    constructor(props) {
        super(props);
        this.handleSubmit = this.handleSubmit.bind(this);
    }
    handleSubmit(e, {formData}) {
        e.preventDefault();

        //
        // Potentially need to manually validate fields here?
        //

        // Send a POST request to the server with the formData
        this.props.dispatch(signUp(formData)).then(({isAuthenticated}) => {
            if (isAuthenticated) {
                // Redirect to the home page if the user is authenticated
                this.props.router.push('/');
            }
        }
    }
    render() {
        const {err} = this.props;

        return (
            <Form onSubmit={this.handleSubmit} error={Boolean(err)}>
                <Form.Input label="Email" name="email" type="text"/>
                <Form.Input label="Password" name="password" type="password"/>
                <Form.Input label="Confirm Password" name="confirmPassword" type="password"/>

                {err &&
                    <Message header="Error" content={err.message} error/>
                }

                <Button size="huge" type="submit" primary>Sign Up</Button>
            </Form>
        );
    }
}

现在,我习惯了常规的语义 UI 库,它有一个表单验证插件。通常,我会在一个单独的 JavaScript 文件中定义这样的规则

$('.ui.form').form({
    fields: {
        email: {
            identifier: 'email',
            rules: [{
                type: 'empty',
                prompt: 'Please enter your email address'
            }, {
                type: 'regExp',
                value: "[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?",
                prompt: 'Please enter a valid email address'
            }]
        },
        password: {
            identifier: 'password',
            rules: [{
                type: 'empty',
                prompt: 'Please enter your password'
            }, {
                type: 'minLength[8]',
                prompt: 'Your password must be at least {ruleValue} characters'
            }]
        },
        confirmPassword: {
            identifier: 'confirmPassword',
            rules: [{
                type: 'match[password]',
                prompt: 'The password you provided does not match'
            }]
        }
    }
});

是否有使用 Semantic UI React 组件验证表单的类似方法?我搜索了文档但没有成功,似乎没有使用这个 Semantic UI React 库进行验证的示例。

我是否需要在handleSubmit函数中手动验证每个字段?解决此问题的最佳方法是什么?谢谢您的帮助!

4

9 回答 9

9

在大多数情况下,您必须手动验证表单。但是,RSUI 包含一些工具可以让事情变得更容易一些,特别是错误支持<Form><Form.Input>

这是我最近整理的一个表格示例。它可以使用一些重构,但它基本上通过将每个输入与状态绑定到一个onChange()函数,并将回调传递给控制加载屏幕的可见性的提交函数和“成功。感谢您提交”部分来工作表格。

export default class MeetingFormModal extends Component {

  constructor(props) {
    super(props)

    this.state = {
      firstName: '',
      lastName: '',
      email: '',
      location: '',
      firstNameError: false,
      lastNameError: false,
      emailError: false,
      locationError: false,
      formError: false,
      errorMessage: 'Please complete all required fields.',
      complete: false,
      modalOpen: false
    }

    this.submitMeetingForm = this.submitMeetingForm.bind(this);
    this.successCallback = this.successCallback.bind(this);
  }


  successCallback() {
    this.setState({
      complete: true
    })
    setTimeout( () => {this.setState({modalOpen: false})}, 5000);
    this.props.hideLoading();
  }

  handleClose = () => this.setState({ modalOpen: false })
  handleOpen = () => this.setState({ modalOpen: true })

  submitMeetingForm() {

    let error = false;

    if (this.state.studentFirstName === '') {
      this.setState({firstNameError: true})
      error = true
    } else {
      this.setState({firstNameError: false})
      error = false
    }
    if (this.state.studentLastName === '') {
      this.setState({lastNameError: true})
      error = true
    } else {
      this.setState({lastNameError: false})
      error = false
    }
    if (this.state.email === '') {
      this.setState({emailError: true})
      error = true
    } else {
      this.setState({emailError: false})
      error = false
    }
    if (this.state.location === '') {
      this.setState({locationError: true})
      error = true
    } else {
      this.setState({locationError: false})
      error = false
    }

    if (error) {
      this.setState({formError: true})
      return
    } else {
      this.setState({formError: false})
    }


    let meeting = {
      first_name: this.state.firstName,
      last_name: this.state.lastName,
      email: this.state.email,
      location: this.state.location,

    this.props.createMeeting(meeting, this.successCallback)
    this.props.showLoading();
  }

  capitalize(string) {
    return string.charAt(0).toUpperCase() + string.slice(1);
  }

  render() {
    return(
      <Modal
        trigger={<Button onClick={this.handleOpen} basic color='blue'>Schedule Now</Button>}
        open={this.state.modalOpen}
        onClose={this.handleClose}
        closeIcon={true}
      >
        <Modal.Header>Schedule Your Interview</Modal.Header>
        <Modal.Content>
          {!this.state.complete ?
          <Modal.Description>
            <Form error={this.state.formError}>
              <Form.Group widths='equal'>
                <Form.Field>
                  <Form.Input required={true} onChange={(e) => this.setState({firstName: e.target.value})} label='First Name' placeholder="First Name..." error={this.state.firstNameError}/>
                </Form.Field>
                <Form.Field>
                  <Form.Input required={true} onChange={(e) => this.setState({lastName: e.target.value})} label='Last Name' placeholder="Last Name..." error={this.state.lastNameError}/>
                </Form.Field>
              </Form.Group>
              <Form.Field >
                <Form.Input required={true} onChange={(e) => this.setState({email: e.target.value})} label='Email' placeholder="Email..." error={this.state.emailError}/>
              </Form.Field>
              <Form.Field>
                <Form.Input required={true} onChange={(e) => this.setState({location: e.target.value})} label='Location' placeholder='City, State/Province, Country...' error={this.state.locationError}/>
              </Form.Field>
            </Form>
          </Modal.Description>
          : 
            <div className='modal-complete'>
              <Image src='/images/check.png' />
              <p>Thanks for scheduling a meeting, {this.capitalize(this.state.name)}. We've received your information and we'll be in touch shortly.</p>
            </div>
          }
        </Modal.Content>
        {!this.state.complete ?
        <Modal.Actions>
          <Button color='red' onClick={this.handleClose}>Close</Button>
          <Button positive icon='checkmark' labelPosition='right' content="Submit" onClick={this.submitMeetingForm} />
        </Modal.Actions>
        : null }
      </Modal>
    )
  }
}

希望有帮助!

于 2017-09-19T02:42:41.810 回答
7

我们甚至有更好的选择,虽然没有由 semantic-ui-react -> Formik + yup
Formik:帮助管理表单状态 Yup:帮助验证该状态

我有以下组件,它基本上是使用语义 UI 反应创建的编辑表单。

import React, { Component } from "react";
import { Button, Form, Modal, Message, Divider } from "semantic-ui-react";
import { Formik } from "formik";
import * as yup from "yup";


class EditAboutGrid extends Component {

  render() {
    const {
      userBasic,
      editBasicModal,
      closeModal
    } = this.props;

    return (
      <Formik
        initialValues={{
          firstName: userBasic.firstName,
          lastName: userBasic.lastName,
          bio: userBasic.bio,
        }}
        validationSchema={yup.object().shape({
          firstName: yup
            .string()
            .required("Name cannot be empty"),
          lastName: yup
            .string()
            .required("Name cannot be empty"),
          bio: yup
            .string()
            .max(1000, "Maximum characters exceed 1000")
            .nullable()
        })}
        onSubmit={(values, actions) => {
          //do your stuff here like api calls
        }}
        render={({
          values,
          errors,
          handleChange,
          handleSubmit,
          isSubmitting,
          dirty,
          setFieldValue
        }) => (
          <Modal open={editBasicModal} size="small">
            <Modal.Header>Your basic details</Modal.Header>
            <Modal.Content scrolling>
              {errors.firstName && <Message error content={errors.firstName} />}
              {errors.lastName && <Message error content={errors.lastName} />}
              {errors.bio && <Message error content={errors.bio} />}

              <Form loading={isSubmitting}>
                <Form.Group inline widths="equal">
                  <Form.Input
                    required
                    label="First Name"
                    fluid
                    type="text"
                    name="firstName"
                    value={values.firstName}
                    onChange={handleChange}
                    error={errors.firstName !== undefined}
                  />
                  <Form.Input
                    required
                    label="Last Name"
                    fluid
                    type="text"
                    name="lastName"
                    value={values.lastName}
                    onChange={handleChange}
                    error={errors.lastName !== undefined}
                  />
                </Form.Group>
                <Form.TextArea
                  label="Bio"
                  type="text"
                  name="bio"
                  value={values.bio}
                  onChange={handleChange}
                  rows={3}
                  error={errors.bio !== undefined}
                />
              </Form>
            </Modal.Content>
            <Modal.Actions open={true}>
              <Button
                onClick={() => (dirty ? closeModal(true) : closeModal(false))}>
                Cancel
              </Button>
              <Button
                primary
                type="submit"
                onClick={handleSubmit}
                loading={isSubmitting}
                disabled={isSubmitting || !isEmpty(errors) || !dirty}>
                Update
              </Button>
            </Modal.Actions>
          </Modal>
        )}
      />
    );
  }
}

这种形式被称为使用:

  <EditAboutGrid
    editBasicModal={this.state.editBasicModal}
    userBasic={this.state.user.basic}
    closeModal={this.closeModal}
  />

initialValues是事情开始的地方。在这里,您将初始/默认值传递给表单的输入。values(在表单中)将从该默认值中选择数据值。

validationSchema是所有验证发生的地方yup

onSubmit将在表单提交时调用。

使用 Formik + yup 处理表单非常容易。我很喜欢它。

于 2019-05-03T14:09:50.770 回答
1

我知道这个问题已经有好几年了,但这是我在使用(相对)较新的 React 功能组件和 Hooks API 时遇到的问题。就我而言,我只是想验证用户输入是一个有效的电子邮件地址。我最终通过下面的代码得到了我正在寻找的行为。

import React, {useState} from 'react';
import { Form } from 'semantic-ui-react'
import EmailValidator from 'email-validator';


function MyFormComponentExample() {
    const [emailInput, setEmail] = useState("");
    const [validEmail, validateEmail] = useState(true);

    return (
    <Form>
        <Form.Input
            icon='envelope'
            iconPosition='left'
            label='Email'
            placeholder='Email Address'
            required
            value={emailInput}
            onChange={e => {
                setEmail(e.target.value);                               
                validateEmail(EmailValidator.validate(e.target.value));
            }}
            error={validEmail ? false : {
                content: 'Please enter a valid email address.',
                pointing: 'below'
            }}
        />
    </Form>
    );
}

export default MyFormComponentExample;

一旦我弄清楚了,我认为这个结构很简单,但如果有人对更好的模式或方法有反馈,我很想听听!

于 2020-10-28T15:02:05.433 回答
1

我是否需要在 handleSubmit 函数中手动验证每个字段?

悲伤,但真实。SUIR目前没有表单验证。但是,您可以使用 HOC 来处理redux-form 之类的表单。

于 2017-02-07T09:28:06.840 回答
1

您可以使用插件进行验证。插件名称:formsy-semantic-ui-react

于 2018-09-28T05:18:42.607 回答
0

我知道这已经有几年的历史了,对于所提出的问题来说并不是一个完整的解决方案,但是今天看的任何人都可能会发现这很有用,因为我一直在寻找相同的东西并遇到了这个线程。虽然 semantic-ui-react 没有我能找到的表单验证,但它有一种很好的方式来显示表单验证错误。您仍然需要自己进行验证。有关它如何显示验证错误的示例,请参阅语义 ui-react 表单文档页面。它还具有显示成功消息的功能。我创建了一个示例,说明如何根据状态控制错误消息。在此示例中,您可以使用“显示性别错误”复选框来切换性别输入上的错误消息。

于 2020-06-04T06:00:59.537 回答
0

下面的代码基本上将状态设置为每个组件名称和关联值。(IE,状态可能看起来像 {marketSide:buy, price:50, quantity:9} 我也将表单错误信息填充到状态中,利用 yup 的默认行为不验证验证模式未提及的字段.

要点:

1) 对 schema.validate(someObjectToValidate, yupProperties) 的调用(其中 someObjectToValidate 就是 this.state),应该传入 {abortEarly:false} 作为属性对象,以覆盖 yups 默认行为以在单个错误发生后停止验证遇到过,因为我们表单的消息组件向用户显示所有错误。

2)如果 yup 验证失败,yup 会抛出异常,因此我们捕获异常并挑选出我们感兴趣的错误信息,并使用此错误更新我们的状态。

3)我们必须使用 this.setState(...) 的“回调形式”,因为 setState 是异步的,因此状态对象的验证仅在状态更新后发生。

4)如果是的验证成功,我们清除我们的错误和errorPath数组。

5)这是一个快速的解决方案,我在每次渲染时检查了几次 errorPaths 数组。最好将 errorPath 和错误信息存储在由组件名称键入的 json 对象中,而不是存储在两个数组中,以改进当前解决方案的(2 个数组 * N 个字段 * N 个潜在错误 = O(2n^2)表现。

6)忽略长样式' <Form.Field control={Radio}>'符号,您可以使用较短的<Input>, <Button>, <Radio>,等样式。此语法与验证无关。也忽略div。

import React, { Component } from 'react'
import { Button, Checkbox, Form, Input, Radio, Select, Message,  Label } from 'semantic-ui-react'
import * as yup from 'yup';


const options = [
  { text: 'buy', value: 'buy' },
  { text: 'sell', value: 'sell' },
]

class OrderEntryV3 extends Component {
  state = {
      errorPaths:[],
      errors:[]
  }

  constructor(props){
      super(props);
  }


  schema = yup.object().shape({
    quantity: yup.number().required().positive().integer(),
    price:  yup.number().required().positive(),
    marketSide: yup.string().required(),
    orderType : yup.string().required()
  });



  handleChange = (e, component) => {
      this.setState({[component.name]:component.value}, ()=>this.schema.validate(this.state, {abortEarly:false})
         .then(valid=>this.setState({errorPaths:[], errors:[]})) //called if the entire form is valid
         .catch(err=>this.setState({errors:err.errors, errorPaths: err.inner.map(i=>i.path) }))) //called if any field is invalid
    };


  render() {

    return (
<div id="oeform-content">
    <div id="oeform-left">
      <Form>
          <Form.Field  error={this.state.errorPaths.includes('marketSide')} name="marketSide" control={Select} label='Market side' options={options} placeholder='market side' onChange={this.handleChange}/>
          <Form.Field  error={this.state.errorPaths.includes('quantity')} type='number' name="quantity" control={Input} label='Quantity' placeholder='quantity' onChange={this.handleChange}/>

          <Form.Group>
              <label><b>Order type</b></label>  
        <Form.Field error={this.state.errorPaths.includes('orderType')} >
          <Radio
            label='market'
            name='orderType'
            value='market'
            checked={this.state.orderType === 'market'}
            onChange={this.handleChange}
          />
        </Form.Field>
        <Form.Field error={this.state.errorPaths.includes('orderType')}>
          <Radio
            label='limit'
            name='orderType'
            value='limit'
            checked={this.state.orderType === 'limit'}
            onChange={this.handleChange}
          />
        </Form.Field>
    </Form.Group>
        <Form.Field error={this.state.errorPaths.includes('price')} name='price' control={Input} type='number' label='Price' placeholder='price' onChange={this.handleChange}/>
        <Form.Field control={Button} disabled={!!this.state.errors.length}>Submit</Form.Field>
        <Message visible={!!this.state.errors.length} warning
        header='Please correct the following issues: '
        list={this.state.errors}/>
      </Form>
    </div>
    <div id="oeform-right">
        <p>{JSON.stringify(this.state)}</p>
    </div>
</div>
    )
  }
}

export default OrderEntryV3
于 2018-10-18T01:06:34.947 回答
-1

对于语义 UI 中的验证表单,您无需任何插件即可轻松实现

<Form.Field
      id='form-input-control-project-name'
      control={Input}
      label='Project Name'
      placeholder='Project name'
      onChange={this.handleChange}
      error={this.state.projectName}
    />

this.state.projectName 在此变量中,您必须存储错误/错误消息

如果值为 false不显示错误,否则显示错误

于 2020-07-31T07:21:23.463 回答
-1

您可以使用Formik进行验证。

我创建了一个库来绑定 Formik 和 Semantic UI React。

https://github.com/JT501/formik-semantic-ui-react

一个简单的例子: Codesandbox

于 2020-11-02T11:13:49.097 回答