【问题标题】:How to apply Form validation for React Material-UI TextField and Select?如何为 React Material-UI TextField 和 Select 应用表单验证?
【发布时间】:2020-05-23 01:54:03
【问题描述】:

我正在尝试在处理 Next() 之前向 TextField 和 Select 添加验证。这是代码(2个组件):

class Quote extends React.Component {
state = {
    activeStep: 0,
    zipCode: '',
    destination: '',
    sedanPrice: '',
    suvPrice: '',
    labelWidth: 0,
};

getStepContent = (step) => {
    switch (step) {
        case 0:
            return (
                <div>
                    <QuoteForm
                        {...this.state}
                        {...this.state.value}
                        handleChange={this.handleChange}
                    />
                </div>
            )
        case 1:
            return (
                <div>
                    <QuotePrice 
                        {...this.state}
                        {...this.state.value}
                    />
                </div>
            )
        default:
            throw new Error('Unknown step');
    }
}

handleNext = () => {
    this.setState(prevState => ({
        activeStep: prevState.activeStep + 1,
    }));
    switch(this.state.activeStep){
        case 0: 
            // Creates an API call for sedan pricing
            API.getPrice(this.state.zipCode, "sedan" + this.state.destination).then(res => {
                let price = res.data;
                let key = Object.keys(price);
                console.log("Sedan price is $" + price[key]);
                this.setState({sedanPrice: price[key]});
            })
            .catch(err => console.log(err));

            // Creates an API call for SUV pricing
            API.getPrice(this.state.zipCode, "suv" + this.state.destination).then(res => {
                let price = res.data;
                let key = Object.keys(price);
                console.log("SUV price is $" + price[key])
                this.setState({suvPrice: price[key]});
            })
            .catch(err => console.log(err));
        break
        case 1:
            console.log('forward to booking page');
            window.location.href = '/booking';
        break
        default: 
            console.log('over');
    }
};

handleBack = () => {
    this.setState(state => ({
        activeStep: state.activeStep - 1,
        sedanPrice: '',
        suvPrice: '',
        destination: '',
        zipCode: '',
    }));
};

handleReset = () => {
    this.setState({
        activeStep: 0,
    });
};

handleChange = event => {
    const { name, value } = event.target;
    this.setState({
        [name]: value,
    });
};

render() {
    const { classes } = this.props;
    const { activeStep } = this.state;
    const steps = ['Pick Up Address', 'Select Your Vehicle'];

    return (
        <React.Fragment>
            <CssBaseline />
            <main className={classes.layout}>
                <Paper className={classes.paper}>
                    <React.Fragment>
                        {activeStep === steps.length ? (
                            <React.Fragment>
                                <Typography variant="h5" gutterBottom>
                                    Thank you for your interest!
                                </Typography>
                            </React.Fragment>
                            ) : (
                            <React.Fragment>
                                {this.getStepContent(activeStep)}
                                <div className={classes.buttons}>
                                    {activeStep !== 0 && (
                                        <Button onClick={this.handleBack} className={classes.button}>
                                            Back
                                        </Button>
                                    )}
                                    <Button
                                        variant="contained"
                                        color="primary"
                                        onClick={this.handleNext}
                                        className={classes.button}
                                    >
                                        {activeStep === steps.length - 1 ? 'Book Now' : 'Next'}
                                    </Button>
                                </div>
                            </React.Fragment>
                            )}
                    </React.Fragment>
                </Paper>
            </main>
        </React.Fragment>
    );
}

}

QuoteForm.js

export class QuoteForm extends React.Component {

state = {
    zipCode: this.props.zipCode,
    destination: this.props.destination,
}

render() {

    const { classes } = this.props;

    return (
        <React.Fragment>
            <Typography variant="h5" align="center">
                Enter your zip code for a quick quote
            </Typography>
            <Grid container>
                <Grid className={classes.TextField} item xs={12} sm={6}>
                    <TextField
                        required
                        id="zip"
                        name="zipCode"
                        label="Zip / Postal code"
                        fullWidth
                        autoComplete="billing postal-code"
                        value={this.props.zipCode}
                        onChange={this.props.handleChange}
                    />
                </Grid>
                <FormControl xs={12} sm={6} className={classes.formControl}>
                    <Select
                        required
                        value={this.props.destination}
                        onChange={this.props.handleChange}
                        input={<Input name="destination" />}
                        displayEmpty
                        name="destination"
                        className={classes.selectEmpty}
                    >
                        <MenuItem value="">
                            <em>Select Your Airport *</em>
                        </MenuItem>
                        <MenuItem name="SAN" value={"SAN"}>San Diego International Airport</MenuItem>
                        <MenuItem name="LAX" value={"LAX"}>Los Angeles International Airport</MenuItem>
                    </Select>
                </FormControl>
            </Grid>
        </React.Fragment>
    );
}

}

我尝试了两种不同的方法。首先,使用 Button disabled 并编写一个函数来处理验证并将 disabled 设置为 false。其次,使用 npm 包处理验证。两者都失败了,因为我是新手。任何帮助,将不胜感激。提前致谢。

【问题讨论】:

标签: reactjs validation material-ui react-material-ui-form-validator


【解决方案1】:

执行以下操作:

  • 保持一个布尔状态,比如errorerrorMessage
  • 在handleNext中,验证他的输入值并将error设置为false,并为错误设置一条消息。
  • 对于材料 ui 文本字段,使用 errorhelperText props 在您的字段旁边很好地设置/显示错误
  • 对于材质 ui Select,使用 FormControl error 属性并将 label 提供给 Select 以便在您的字段旁边很好地设置/显示错误
  • 在修复错误之前不要让用户转到下一个表单。
  • errorerrorMessage 传递给QuoteForm 组件。

密码箱中的Working copy of your code is here

状态

state = {
    activeStep: 0,
    zipCode: "",
    destination: "",
    sedanPrice: "",
    suvPrice: "",
    labelWidth: 0,
    error: false, //<---- here
    errorMessage: {} //<-----here
  };

handleNext

handleNext = () => {
    let isError = false;
    if (this.state.zipCode.length < 2) {
      isError = true;
      this.setState({
        error: true,
        errorMessage: { zipCode: "enter correct zipcode" }
      });
    } 
    if (this.state.destination === '') {
      isError = true;
      this.setState(prev => ({
        ...prev,
        error: true,
        errorMessage: { ...prev.errorMessage, destination: "enter correct destination" }
      }))
    }  if(!isError){
      //add else if for validating other fields (if any)
      this.setState(prevState => ({
        activeStep: prevState.activeStep + 1,
        error: false,
        errorMessage: {}
      }));
    }
  ...

Mui 文本框

          <TextField
              error={!!this.props.errorMessage.zipCode}
              required
              id="zip"
              name="zipCode"
              label="Zip / Postal code"
              fullWidth
              autoComplete="billing postal-code"
              value={this.props.zipCode}
              onChange={this.props.handleChange}
              helperText={
                this.props.errorMessage.zipCode &&
                this.props.errorMessage.zipCode
              }
            />

Mui Select使用

<FormControl xs={12} sm={6} error={this.props.error}>
            <Select
              error={!!this.props.errorMessage.destination}
              label="enter cor dest"
              required
              value={this.props.destination}
              onChange={this.props.handleChange}
              input={<Input name="destination" />}
              displayEmpty
              name="destination"
            >
              <MenuItem value="">
                <em>Select Your Airport *</em>
              </MenuItem>
              <MenuItem name="SAN" value={"SAN"}>
                San Diego International Airport
              </MenuItem>
              <MenuItem name="LAX" value={"LAX"}>
                Los Angeles International Airport
              </MenuItem>
            </Select>
            <FormHelperText>
              {this.props.errorMessage.destination}
            </FormHelperText>
          </FormControl>

【讨论】:

  • 非常感谢。我尝试了类似的方法,但使用的是 handleChange 函数而不是 handleNext()。它没有用。这非常适合邮政编码验证。我是否应该在您在 handleNext 中为 zipCode 添加的 if/else 下方添加 if/else for Select 表单?
  • 是的,您可以添加多个 ifs 来进行验证...我已经更新了覆盖选择的答案以及更新了代码框(相同的链接)...当验证变得庞大时,那么可以考虑使用yup..等库。
  • 谢谢。我看到你做了什么。它按原样工作。做得好。我将 zipCode 的 if 语句更改为在范围内以覆盖 MySQL 数据库中的语句(总共大约 120 个)。唯一的问题是该范围内的一些邮政编码不在服务范围内,并且数据库中没有它们的价格。从有经验的角度来看,最好进行额外的 API 调用来检查邮政编码是否在数据库中并显示这些错误消息,或者在代码中以数组形式列出邮政编码并循环遍历它?
猜你喜欢
  • 1970-01-01
  • 2021-08-30
  • 2016-08-23
  • 1970-01-01
  • 2020-08-06
  • 2021-02-11
  • 2022-01-04
  • 2020-09-30
  • 1970-01-01
相关资源
最近更新 更多