Проверка формы с помощью Semantic-UI-React

Я использую официальные компоненты Semantic UI React для создания веб-приложения. У меня есть форма на моей странице регистрации, которая содержит поле электронной почты, поле пароля и поле подтверждения пароля.

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>
        );
    }
}

Теперь я привык к обычной библиотеке семантического пользовательского интерфейса, в которой есть надстройка проверки формы. Обычно я определяю такие правила в отдельном файле 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? Как лучше всего решить эту проблему? Спасибо за помощь!


person TFischer    schedule 18.01.2017    source источник
comment
В процессе изучения React я наткнулся на формы, которые, как мне казалось, могут быть в React как часть его основных функций. Но, к сожалению, это не так. Это стало причиной того, что мне не нравится много реагировать по сравнению с Angular.   -  person Pankaj Prakash    schedule 31.05.2020
comment
@PankajPrakash, этому вопросу уже несколько лет, и сейчас есть много отличных вариантов для проверки формы. Сейчас я использую formik и yup, которые отлично справляются с проверкой форм.   -  person TFischer    schedule 02.06.2020


Ответы (9)


У нас даже есть вариант получше, хотя его и не предоставляет semantic-ui-react -> Formik + да
Formik: помогает в управлении состоянием формы Да: помогает в проверке этого состояния

У меня есть компонент ниже, который в основном представляет собой форму редактирования, созданную с помощью semantic-ui-react.

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 очень проста. Я люблю это.

person TheCoder    schedule 03.05.2019
comment
Просто примечание для людей, использующих этот код. Вам потребуется функция isEmpty() следующим образом: `` function isEmpty (arg) {return (arg == null || // Проверяем наличие null или undefined arg.length === 0 || // Проверяем пустую строку (бонус проверить наличие пустого массива) (typeof arg === 'object' && Object.keys (arg) .length === 0) // Проверить наличие пустого объекта или массива); } `` Функция Formik render() устарела в самой последней версии на 2020-12-30. - person gbmhunter; 30.12.2020
comment
Или вы можете импортировать его из lodash - person TheCoder; 31.12.2020

По большей части вам приходится проверять формы вручную. Однако 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>
    )
  }
}

Надеюсь, это поможет!

person jmknoll    schedule 19.09.2017
comment
let meeting = { ... не закрыто - person Juan Salvador; 07.04.2019
comment
Теперь кажется, что я могу избежать Formik или Redux-форм для управления любым эфимерным состоянием формы. Хороший образец, спасибо @jmknoll - person Juan Salvador; 07.04.2019

Должен ли я вместо этого проверять каждое поле вручную в функции handleSubmit?

Печально, но факт. SUIR в настоящее время не имеет проверки формы. Однако вы можете использовать HOC для работы с такими формами, как redux-form.

person Oleksandr Fediashov    schedule 07.02.2017

Вы можете использовать плагин для проверки. Название плагина: formy-semantic-ui-react

person Trupti    schedule 28.09.2018
comment
Это то, чем я закончил. Но очень жаль, что semantic-ui-react не имеет этой возможности, а semantic-ui. formsy-semantic-ui-react - это сторонний пакет, поэтому я обеспокоен тем, что он не получит такой же поддержки, как официальный пакет. - person TFischer; 28.09.2018

Я знаю, что этому вопросу уже несколько лет, но я боролся с этим, используя (относительно) новые функциональные компоненты 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;

Как только я понял это, я подумал, что эта структура достаточно проста, но если у кого-то есть отзывы о лучшем шаблоне или подходе для этого, я хотел бы это услышать!

person Justin    schedule 28.10.2020

Приведенный ниже код по существу устанавливает состояние для каждого имени компонента и связанного значения. (IE, состояние может выглядеть так: {marketSide: buy, price: 50, quantity: 9} Я также помещаю информацию об ошибках формы в состояние, используя в своих интересах поведение по умолчанию, чтобы не проверять поля, которые не упоминаются в схеме проверки. .

Важные точки:

1) Вызов schema.validate (someObjectToValidate, yupProperties) (где someObjectToValidate - это просто this.state) должен передать {abortEarly: false} в качестве объекта свойств, чтобы переопределить поведение по умолчанию для остановки проверки после появления единственной ошибки были обнаружены, поскольку компонент сообщения нашей формы отображает пользователю все ошибки.

2) Если да, проверка не удалась, да, выдает исключение, поэтому мы перехватываем исключение, выбираем интересующую нас информацию об ошибке и обновляем наше состояние с помощью этой ошибки.

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
person mancini0    schedule 18.10.2018

Я понимаю, что ему уже несколько лет, и это не полное решение заданного вопроса, но любой, кто ищет сегодня, может найти это полезным, поскольку я искал то же самое и наткнулся на эту ветку. Хотя у semantic-ui-react нет проверки формы, которую я могу найти, но у нее есть хороший способ показать ошибки проверки формы. Вам все равно придется проводить валидацию самостоятельно. См. страницу документации по формам semantic-ui-react, чтобы увидеть, как это показывает ошибки проверки. Он также имеет функцию отображения сообщения об успешном завершении. Я создал пример того, как можно контролировать сообщение об ошибке на основе государство. В этом примере вы можете использовать флажок Показать ошибку пола, чтобы переключить сообщение об ошибке на поле ввода Пол.

person Sonny N    schedule 04.06.2020
comment
Где в документации форм Semantic UI React что-то говорится о валидации? - person BudwiseЯ; 08.07.2020

Для проверки формы в семантическом интерфейсе вы можете просто достичь без какого-либо плагина

<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 не отображается ошибка в противном случае отображается ошибка

person vinayak lakhotiya    schedule 31.07.2020

Для проверки можно использовать Formik.

И я создал библиотеку для связывания Formik и Semantic UI React.

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

Быстрый пример: Codesandbox

person JT501    schedule 02.11.2020