使用reactjs单击“提交”按钮后,无法显示helperText吗?

问题描述

我是此下拉验证的新手,我想在选择下拉字段(或我们选择但再次选择-1菜单项值时,在下拉菜单底部显示辅助文本。在这里,我面临的问题很少。

  1. 辅助文字无法显示红色。

  2. 对我来说,它在第50行显示错误,但在沙盒中却未显示任何错误

  3. 虽然提交的表单的下拉字段为空(-1),但它应该显示helpertext。

提交表单时,我无法显示助手文本。

在这里尝试过这种方式:

class Sample extends React.Component<Props,State> {
  constructor(props: Props) {
    super(props);
    this.state = {
      channel: -1,sports: -1,movie: ""
    };
  }
  handleChange = (e: any) => {
    this.setState({ channel: e.target.value });
  };
  handleSports = (e: any) => {
    this.setState({ sports: e.target.value });
  };

  handleMovie = (e: any) => {
    this.setState({ movie: e.target.value });
  };

  Valid = () => {
    const errors = { channel: "",sports: "",movie: "" };
    if (!this.state.channel) {
      errors.channel = "Please select channel";
    }
    if (!this.state.sports) {
      errors.sports = "select Sports";
    }
    if (!this.state.movie) {
      errors.movie = "select movie";
    }
    return {
      errors,isSubmit: Object.keys(errors).length === 0
    };
  };

  handleSubmit = (e: any) => {
    e.preventDefault();
    const data = {
      channel: this.state.channel,sports: this.state.sports,movie: this.state.movie
    };
    console.log(data);
  };

  render() {
    const { errors,isSubmit } = this.Valid();
    return (
      <>
        <FormControl>
          <Select
            defaultValue={-1}
            onChange={this.handleChange}
            displayEmpty
            inputProps={{ "aria-label": "Without label" }}
          >
            <MenuItem value={-1}>Select Channel</MenuItem>
            <MenuItem value={10}>Sports</MenuItem>
            <MenuItem value={20}>Entertainment</MenuItem>
          </Select>
          {!this.state.channel ? (
            <FormHelperText>{errors.channel}</FormHelperText>
          ) : null}
        </FormControl>
        {this.state.channel === 10 ? (
          <div>
            <FormControl>
              <Select
                defaultValue={-1}
                onChange={this.handleSports}
                displayEmpty
                inputProps={{ "aria-label": "Without label" }}
              >
                <MenuItem value={-1}>Select </MenuItem>
                <MenuItem value={10}>Star sports 1</MenuItem>
                <MenuItem value={20}>Star sports 2</MenuItem>
              </Select>
              {!this.state.sports ? (
                <FormHelperText>{errors.sports}</FormHelperText>
              ) : null}
            </FormControl>
          </div>
        ) : this.state.channel === 20 ? (
          <div>
            <FormControl>
              <Select
                defaultValue={-1}
                onChange={this.handleMovie}
                displayEmpty
                inputProps={{ "aria-label": "Without label" }}
              >
                <MenuItem value={-1}>Select</MenuItem>
                <MenuItem value={10}>Star Movies</MenuItem>
                <MenuItem value={20}>ABC</MenuItem>
              </Select>
              {!this.state.movie ? (
                <FormHelperText>{errors.movie}</FormHelperText>
              ) : null}
            </FormControl>
          </div>
        ) : null}
        <div>
          <Button disabled={isSubmit} onClick={this.handleSubmit}>
            Submit
          </Button>
        </div>
      </>
    );
  }
}
export default Sample;

Here is the sample

有人可以帮助我进行此查询吗?

解决方法

问题1

无法显示红色的辅助文字。

您可以使用FormControlFormHelperText上的error道具将文本涂成红色。 FormControl实际上为其包装的字段提供了上下文,因此最容易在此处设置error属性。

<FormControl error={!!errors?.channel}>
  ...
  {errors?.channel && <FormHelperText>{errors.channel}</FormHelperText>}
</FormControl>

问题2

对我来说,它在第50行显示错误,但在沙盒中却没有 显示任何错误。

不幸的是,对于您而言,第50行由本地组成没有更多的上下文,这里没有什么要解决的。随时用更多详细信息更新您的问题,也许是违规行的代码片段以及错误消息的副本。

问题3

虽然提交的表单的下拉字段为空(-1),但应该 显示辅助文字。

在这里,我认为应该进行一些重构。

  1. 禁用第一个“占位符”选择选项,它实际上应该是可选的,但仍可以是defaultValue。这意味着一旦选择了 valid 选项,就只能选择其他有效选项,而永远不会选择禁用的选项。这也意味着该字段仅在用户未选择任何选项时才有效。

    <MenuItem disabled value={-1}>
      Select Channel
    </MenuItem>
    <MenuItem value={10}>Sports</MenuItem>
    <MenuItem value={20}>Entertainment</MenuItem>
    
  2. 您有2个级别的选择字段。当用户更改根channel的状态时,请重置moviesports状态。

  3. 更改状态形状以包含 some 错误/验证对象,该对象将包含错误和表单可提交状态。状态更新时重置。

    componentDidUpdate(prevProps,prevState) {
      // If channel updated then reset "nested" select values
      if (prevState.channel !== this.state.channel) {
        this.setState({
          sports: null,movie: null
        });
      }
    
      // Clear error state upon change,next validation to occur next submit attempt
      if (!prevState.validation.canSubmit && !this.state.validation.canSubmit) {
        this.setState({
          validation: {
            canSubmit: true
          }
        });
      }
    }
    
  4. name处理程序中要访问的选择输入添加onChange属性;这些应该匹配状态中的名称。另外,由于您有名称,因此可以将onChange处理程序简化为单个输入更改处理程序。

    <Select
      defaultValue={-1}
      onChange={this.handleChange}
      displayEmpty
      inputProps={{ "aria-label": "Without label" }}
      name="channel" // <-- add name attribute (add for other inputs as well)
    >
    

处理程序

    handleChange = (e: any) => {
      const { name,value } = e.target;
      this.setState({ [name]: value } as Pick<
        State,"channel" | "movie" | "sports"
      >);
    };
  1. 由于无法选择sports AND movie,因此请使用某些分支逻辑来验证一个或另一个取决于channel,即,如果期望sports有一个值,那么movie从不有一个值,反之亦然。

    Valid = ({ channel,sports,movie }): Validation => {
      const errors: Errors = {};
    
      if (!channel) {
        errors.channel = "Please select channel";
      } else {
        if (channel === 10) {
          if (!sports) {
            errors.sports = "select Sports";
          }
        } else {
          if (!movie) {
            errors.movie = "select movie";
          }
        }
      }
    
      return {
        errors,canSubmit: !Object.keys(errors).length
      };
    };
    
  2. 将表单验证移至onSubmit处理程序,如果验证的“ canSubmit”状态为false,则禁用提交按钮。

    handleSubmit = (e: any) => {
      e.preventDefault();
      const { channel,movie,sports } = this.state;
    
      const validation = this.Valid({ channel,sports });
    
      if (validation.canSubmit) {
        window.alert("SUBMIT!!");
      } else {
        console.log("errors",validation.errors);
        this.setState({ validation });
      }
    };
    

Edit unable-to-validate-dropdown-once-we-click-on-the-submit-button-using-reactjs

完整代码

由于我几乎没有打字经验,所以我会提前道歉。只需快速阅读一下语法即可。以下内容在链接的沙箱中具有零错误/警告。

import React from "react";
import {
  FormControl,Select,MenuItem,FormHelperText,Button
} from "@material-ui/core";

interface Props {}

interface Errors {
  channel?: string;
  sports?: string;
  movie?: string;
}

interface Validation {
  errors?: Errors;
  canSubmit: boolean;
}

interface State {
  channel: number;
  sports: number;
  movie: string;
  validation: Validation;
}

class Sample extends React.Component<Props,State> {
  constructor(props: Props) {
    super(props);
    this.state = {
      channel: null,sports: null,movie: null,validation: {
        canSubmit: true
      }
    };
  }

  componentDidUpdate(prevProps,prevState) {
    // If channel updated then reset "nested" select values
    if (prevState.channel !== this.state.channel) {
      this.setState({
        sports: null,movie: null
      });
    }

    // Clear error state upon change,next validation to occur next submit attempt
    if (!prevState.validation.canSubmit && !this.state.validation.canSubmit) {
      this.setState({
        validation: {
          canSubmit: true
        }
      });
    }
  }

  handleChange = (e: any) => {
    const { name,value } = e.target;
    this.setState({ [name]: value } as Pick<
      State,"channel" | "movie" | "sports"
    >);
  };

  Valid = ({ channel,movie }): Validation => {
    const errors: Errors = {};

    if (!channel) {
      errors.channel = "Please select channel";
    } else {
      if (channel === 10) {
        if (!sports) {
          errors.sports = "select Sports";
        }
      } else {
        if (!movie) {
          errors.movie = "select movie";
        }
      }
    }

    return {
      errors,canSubmit: !Object.keys(errors).length
    };
  };

  handleSubmit = (e: any) => {
    e.preventDefault();
    const { channel,sports } = this.state;

    const validation = this.Valid({ channel,sports });

    if (validation.canSubmit) {
      window.alert("SUBMIT!!");
    } else {
      console.log("errors",validation.errors);
      this.setState({ validation });
    }
  };

  render() {
    const {
      validation: { canSubmit,errors }
    } = this.state;

    return (
      <>
        <FormControl error={!!errors?.channel}>
          <Select
            defaultValue={-1}
            onChange={this.handleChange}
            displayEmpty
            inputProps={{ "aria-label": "Without label" }}
            name="channel"
          >
            <MenuItem disabled value={-1}>
              Select Channel
            </MenuItem>
            <MenuItem value={10}>Sports</MenuItem>
            <MenuItem value={20}>Entertainment</MenuItem>
          </Select>
          {errors?.channel && <FormHelperText>{errors.channel}</FormHelperText>}
        </FormControl>

        {this.state.channel === 10 && (
          <div>
            <FormControl error={!!errors?.sports}>
              <Select
                defaultValue={-1}
                onChange={this.handleChange}
                displayEmpty
                inputProps={{ "aria-label": "Without label" }}
                name="sports"
              >
                <MenuItem disabled value={-1}>
                  Select{" "}
                </MenuItem>
                <MenuItem value={10}>Star sports 1</MenuItem>
                <MenuItem value={20}>Star sports 2</MenuItem>
              </Select>
              {errors?.sports && (
                <FormHelperText>{errors.sports}</FormHelperText>
              )}
            </FormControl>
          </div>
        )}

        {this.state.channel === 20 && (
          <div>
            <FormControl error={!!errors?.movie}>
              <Select
                defaultValue={-1}
                onChange={this.handleChange}
                displayEmpty
                inputProps={{ "aria-label": "Without label" }}
                name="movie"
              >
                <MenuItem disabled value={-1}>
                  Select
                </MenuItem>
                <MenuItem value={10}>Star Movies</MenuItem>
                <MenuItem value={20}>ABC</MenuItem>
              </Select>
              {errors?.movie && (
                <FormHelperText error>{errors.movie}</FormHelperText>
              )}
            </FormControl>
          </div>
        )}

        <div>
          <Button disabled={!canSubmit} onClick={this.handleSubmit}>
            Submit
          </Button>
        </div>
      </>
    );
  }
}
export default Sample;