我正在使用官方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库,它有一个Form Validation addon。通常,我会在单独的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
函数中手动验证每个字段?解决此问题的最佳方法是什么?谢谢你的帮助!
答案 0 :(得分:5)
在大多数情况下,您必须手动验证表单。但是,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>
)
}
}
希望有所帮助!
答案 1 :(得分:1)
我们甚至有一个更好的选择,尽管语义ui-react没有提供-> Formik + yup
Formik:帮助管理表单状态
是的:有助于验证该状态
我有以下组件,基本上是使用语义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处理表单非常简单。我很喜欢。
答案 2 :(得分:0)
我是否需要在handleSubmit中手动验证每个字段 功能
很伤心,但也是如此。 SUIR doesn't have目前正在进行验证。但是,您可以使用HOC来处理redux-form等表单。
答案 3 :(得分:0)
您可以使用插件进行验证。 插件名称:formsy-semantic-ui-react
答案 4 :(得分:0)
以下代码本质上将状态设置为每个组件名称和关联值。 (即,状态可能看起来像{marketSide:buy,价格:50,数量:9}我也将表单错误信息也填充到状态中,利用yup的默认行为来不验证验证模式未提及的字段
重要点:
1)对schema.validate(someObjectToValidate,yupProperties)的调用(其中someObjectToValidate只是this.state),应传入{abortEarly:false}作为属性对象,以覆盖yups默认行为以在一次由于表单的消息组件向用户显示了所有错误,因此遇到了一个错误。
2)如果yup验证失败,则yup会引发异常,因此我们会捕获该异常并提取我们感兴趣的错误信息,并使用此错误更新状态。
3)由于setState是异步的,因此必须使用this.setState(...)的“回调形式”,以便仅在状态更新后进行状态对象的验证。
4)如果yup验证成功,我们将清除错误和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
答案 5 :(得分:0)
我知道这已经有几年历史了,它并不是一个完整的解决方案,但是今天遇到的任何人都可以找到有用的方法,因为我一直在寻找相同的方法并遇到了这个问题。尽管语义UI反应没有我可以找到的表单验证,但是它具有显示表单验证错误的好方法。您仍然必须自己进行验证。有关如何显示验证错误的示例,请参见semantic-ui-react forms documentation page。它还具有显示成功消息的功能。我创建了example,说明如何根据状态控制错误消息。在此示例中,您可以使用“显示性别错误”复选框在“性别”输入上切换错误消息。
答案 6 :(得分:0)
我知道这个问题已经有好几年了,但这是我在使用(相对)较新的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;
一旦我弄清楚了,我认为这种结构很简单,但是如果有人对执行此操作的更好模式或方法有反馈,我将很乐意听!
答案 7 :(得分:0)
您可以使用Formik进行验证。
我创建了一个库来绑定Formik和语义UI React。
https://github.com/JT501/formik-semantic-ui-react
一个简单的例子: Codesandbox
答案 8 :(得分:-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 在此变量中,您必须存储错误/错误消息
如果值为假不显示错误否则显示错误