问题描述
我是此下拉验证的新手,我想在选择下拉字段(或我们选择但再次选择-1
菜单项值时,在下拉菜单的底部显示辅助文本。在这里,我面临的问题很少。
提交表单时,我无法显示助手文本。
我在这里尝试过这种方式:
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;
有人可以帮助我进行此查询吗?
解决方法
问题1
无法显示红色的辅助文字。
您可以使用FormControl
或FormHelperText
上的error
道具将文本涂成红色。 FormControl
实际上为其包装的字段提供了上下文,因此最容易在此处设置error
属性。
<FormControl error={!!errors?.channel}>
...
{errors?.channel && <FormHelperText>{errors.channel}</FormHelperText>}
</FormControl>
问题2
对我来说,它在第50行显示错误,但在沙盒中却没有 显示任何错误。
不幸的是,对于您而言,第50行由本地组成没有更多的上下文,这里没有什么要解决的。随时用更多详细信息更新您的问题,也许是违规行的代码片段以及错误消息的副本。
问题3
虽然提交的表单的下拉字段为空(-1),但应该 显示辅助文字。
在这里,我认为应该进行一些重构。
-
禁用第一个“占位符”选择选项,它实际上应该是可选的,但仍可以是defaultValue。这意味着一旦选择了 valid 选项,就只能选择其他有效选项,而永远不会选择禁用的选项。这也意味着该字段仅在用户未选择任何选项时才有效。
<MenuItem disabled value={-1}> Select Channel </MenuItem> <MenuItem value={10}>Sports</MenuItem> <MenuItem value={20}>Entertainment</MenuItem>
-
您有2个级别的选择字段。当用户更改根
channel
的状态时,请重置movie
和sports
状态。 -
更改状态形状以包含 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 } }); } }
-
向
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"
>);
};
-
由于无法选择
sports
ANDmovie
,因此请使用某些分支逻辑来验证一个或另一个取决于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 }; };
-
将表单验证移至
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 }); } };
完整代码
由于我几乎没有打字经验,所以我会提前道歉。只需快速阅读一下语法即可。以下内容在链接的沙箱中具有零错误/警告。
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;