如何在表单为子 ReactJS 的模态中禁用提交按钮
How to disable submit button in modal where the form is children ReactJS
我对 Javascript 和 React 经验不多,我需要在提交表单时禁用模态中的操作按钮,我已经搜索了互联网但没有找到解决方案。
项目结构如下:
国家列表:
import {
alpha,
Button,
makeStyles,
Paper,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow
} from "@material-ui/core";
import React, { useState } from "react";
import CountryForm from "./CountryForm";
import Popup from "../../components/Popup";
import Notification from "../../components/Notification";
import * as countryService from "../../services/countryService";
const useStyles = makeStyles((theme) => ({
table: {
"& thead th": {
fontWeight: "600",
color: theme.palette.primary.main,
backgroundColor: alpha(theme.palette.primary.light, 0.07)
},
"& tbody td": {
fontWeight: "400"
},
"& tbody tr:hover": {
backgroundColor: "#fffbf2",
cursor: "pointer"
}
},
addButton: {
marginBottom: theme.spacing(2)
}
}));
function Countries(props) {
const classes = useStyles();
const [openPopup, setOpenPopup] = useState(false);
const [records, setRecords] = useState(countryService.getCountries());
const [notify, setNotify] = useState({
isOpen: false,
message: "",
type: ""
});
const handleClose = () => setOpenPopup(false);
return (
<div>
<h1>Countries</h1>
<Button
variant="contained"
color="primary"
className={classes.addButton}
onClick={() => {
setOpenPopup(true);
}}
>
Add
</Button>
<TableContainer component={Paper}>
<Table
className={classes.table}
size="small"
aria-label="a dense table"
>
<TableHead>
<TableRow>
<TableCell align="left">Abbreviation</TableCell>
<TableCell align="left">Name</TableCell>
<TableCell align="right"></TableCell>
</TableRow>
</TableHead>
<TableBody>
{records &&
records.map((row) => (
<TableRow key={row.id}>
<TableCell align="left">{row.abbreviation}</TableCell>
<TableCell align="left">{row.name}</TableCell>
<TableCell align="right"></TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
<Popup openPopup={openPopup} setOpenPopup={setOpenPopup}>
<CountryForm
handleClose={handleClose}
setRecords={setRecords}
setNotify={setNotify}
/>
</Popup>
<Notification notify={notify} setNotify={setNotify} />
</div>
);
}
export default Countries;
国家形式:
import React from "react";
import { Grid, makeStyles } from "@material-ui/core";
import { Field, Form, Formik } from "formik";
import { TextField } from "formik-material-ui";
import * as Yup from "yup";
import * as countryService from "../../services/countryService";
const useStyles = makeStyles((theme) => ({
itemGrid: {
marginBottom: theme.spacing(1)
}
}));
const initialValues = {
id: 0,
abbreviation: "",
name: ""
};
const validationSchema = Yup.object({
abbreviation: Yup.string().required().min(2).max(2),
name: Yup.string().required().max(80)
});
function CountryForm(props) {
const classes = useStyles();
const { handleClose, setRecords, setNotify } = props;
function _onSubmit(fields, { setSubmitting }) {
return fetch(countryService.insertCountry(fields))
.then(() => {
//setSubmitting(false);
handleClose();
setRecords(countryService.getCountries());
setNotify({
isOpen: true,
message: `Added successfully`,
type: "success"
});
})
.cath((err) => {
alert(err);
//setSubmitting(false);
});
}
return (
<Formik
enableReinitialize={true}
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={_onSubmit}
>
{({ errors, touched, isSubmitting }) => {
return (
<Form id="form">
<Grid container direction="row">
<Grid className={classes.itemGrid} item xs={12}>
<Field
name="abbreviation"
label="Abbreviation"
margin="dense"
variant="outlined"
disabled={isSubmitting}
component={TextField}
/>
</Grid>
<Grid className={classes.itemGrid} item xs={12}>
<Field
name="name"
type="text"
fullWidth
label="Name"
margin="dense"
variant="outlined"
disabled={isSubmitting}
component={TextField}
/>
</Grid>
</Grid>
</Form>
);
}}
</Formik>
);
}
export default CountryForm;
模态:
import React from "react";
import {
Dialog,
DialogTitle,
DialogContent,
makeStyles,
Typography,
Divider,
DialogActions,
Button,
Grid,
Box
} from "@material-ui/core";
const useStyles = makeStyles((theme) => ({
dialogWrapper: {
padding: theme.spacing(2),
position: "absolute",
top: theme.spacing(5)
},
dialogTitle: {
paddingRight: 0
},
button: {
margin: theme.spacing(0.5),
textTransform: "none"
},
buttonsContainer: {
display: "flex",
flex: "0 0 auto",
justifyContent: "flex-end",
width: "100%",
height: "100%"
},
buttons: {
display: "flex"
}
}));
function Popup(props) {
const classes = useStyles();
const { title, children, openPopup, setOpenPopup, ...rest } = props;
return (
<Dialog
{...rest}
open={openPopup}
maxWidth="sm"
classes={{ paper: classes.dialogWrapper }}
>
<DialogTitle dividers="true" className={classes.dialogTitle}>
<div style={{ display: "flex" }}>
<Typography variant="h4" component="div" style={{ flexGrow: 1 }}>
Country
</Typography>
</div>
</DialogTitle>
<Divider />
<DialogContent direction="row">{children}</DialogContent>
<DialogActions>
<Grid container className={classes.buttonsContainer}>
<Box className={classes.buttons}>
<Button
className={classes.button}
variant="contained"
color="primary"
type="submit"
form="form"
>
Save
</Button>
<Button
className={classes.button}
color="default"
fullWidth
onClick={() => {
setOpenPopup(false);
}}
>
Cancel
</Button>
</Box>
</Grid>
</DialogActions>
</Dialog>
);
}
export default Popup;
Print submiting
我把代码放在沙箱里:
https://codesandbox.io/s/react-list-modal-form-qzn2b
谢谢你的帮助!
您可以使用 Popup 包装通过 Formik 呈现的表单,而不是用 Popup 包装整个 CountryForm,这样做我们现在将能够访问 Formik 提供的 isSubmitting
道具。
<Formik
enableReinitialize={true}
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={_onSubmit}
>
{({ errors, touched, isSubmitting }) => {
return (
<Popup
openPopup={openPopup}
setOpenPopup={setOpenPopup}
disableSave={isSubmitting}
>
<Form id="form">
<Grid container direction="row">
<Grid className={classes.itemGrid} item xs={12}>
<Field
name="abbreviation"
label="Abbreviation"
margin="dense"
variant="outlined"
disabled={isSubmitting}
component={TextField}
/>
</Grid>
<Grid className={classes.itemGrid} item xs={12}>
<Field
name="name"
type="text"
fullWidth
label="Name"
margin="dense"
variant="outlined"
disabled={isSubmitting}
component={TextField}
/>
</Grid>
</Grid>
</Form>
</Popup>
);
}}
</Formik>
我对 Javascript 和 React 经验不多,我需要在提交表单时禁用模态中的操作按钮,我已经搜索了互联网但没有找到解决方案。
项目结构如下:
国家列表:
import {
alpha,
Button,
makeStyles,
Paper,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow
} from "@material-ui/core";
import React, { useState } from "react";
import CountryForm from "./CountryForm";
import Popup from "../../components/Popup";
import Notification from "../../components/Notification";
import * as countryService from "../../services/countryService";
const useStyles = makeStyles((theme) => ({
table: {
"& thead th": {
fontWeight: "600",
color: theme.palette.primary.main,
backgroundColor: alpha(theme.palette.primary.light, 0.07)
},
"& tbody td": {
fontWeight: "400"
},
"& tbody tr:hover": {
backgroundColor: "#fffbf2",
cursor: "pointer"
}
},
addButton: {
marginBottom: theme.spacing(2)
}
}));
function Countries(props) {
const classes = useStyles();
const [openPopup, setOpenPopup] = useState(false);
const [records, setRecords] = useState(countryService.getCountries());
const [notify, setNotify] = useState({
isOpen: false,
message: "",
type: ""
});
const handleClose = () => setOpenPopup(false);
return (
<div>
<h1>Countries</h1>
<Button
variant="contained"
color="primary"
className={classes.addButton}
onClick={() => {
setOpenPopup(true);
}}
>
Add
</Button>
<TableContainer component={Paper}>
<Table
className={classes.table}
size="small"
aria-label="a dense table"
>
<TableHead>
<TableRow>
<TableCell align="left">Abbreviation</TableCell>
<TableCell align="left">Name</TableCell>
<TableCell align="right"></TableCell>
</TableRow>
</TableHead>
<TableBody>
{records &&
records.map((row) => (
<TableRow key={row.id}>
<TableCell align="left">{row.abbreviation}</TableCell>
<TableCell align="left">{row.name}</TableCell>
<TableCell align="right"></TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
<Popup openPopup={openPopup} setOpenPopup={setOpenPopup}>
<CountryForm
handleClose={handleClose}
setRecords={setRecords}
setNotify={setNotify}
/>
</Popup>
<Notification notify={notify} setNotify={setNotify} />
</div>
);
}
export default Countries;
国家形式:
import React from "react";
import { Grid, makeStyles } from "@material-ui/core";
import { Field, Form, Formik } from "formik";
import { TextField } from "formik-material-ui";
import * as Yup from "yup";
import * as countryService from "../../services/countryService";
const useStyles = makeStyles((theme) => ({
itemGrid: {
marginBottom: theme.spacing(1)
}
}));
const initialValues = {
id: 0,
abbreviation: "",
name: ""
};
const validationSchema = Yup.object({
abbreviation: Yup.string().required().min(2).max(2),
name: Yup.string().required().max(80)
});
function CountryForm(props) {
const classes = useStyles();
const { handleClose, setRecords, setNotify } = props;
function _onSubmit(fields, { setSubmitting }) {
return fetch(countryService.insertCountry(fields))
.then(() => {
//setSubmitting(false);
handleClose();
setRecords(countryService.getCountries());
setNotify({
isOpen: true,
message: `Added successfully`,
type: "success"
});
})
.cath((err) => {
alert(err);
//setSubmitting(false);
});
}
return (
<Formik
enableReinitialize={true}
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={_onSubmit}
>
{({ errors, touched, isSubmitting }) => {
return (
<Form id="form">
<Grid container direction="row">
<Grid className={classes.itemGrid} item xs={12}>
<Field
name="abbreviation"
label="Abbreviation"
margin="dense"
variant="outlined"
disabled={isSubmitting}
component={TextField}
/>
</Grid>
<Grid className={classes.itemGrid} item xs={12}>
<Field
name="name"
type="text"
fullWidth
label="Name"
margin="dense"
variant="outlined"
disabled={isSubmitting}
component={TextField}
/>
</Grid>
</Grid>
</Form>
);
}}
</Formik>
);
}
export default CountryForm;
模态:
import React from "react";
import {
Dialog,
DialogTitle,
DialogContent,
makeStyles,
Typography,
Divider,
DialogActions,
Button,
Grid,
Box
} from "@material-ui/core";
const useStyles = makeStyles((theme) => ({
dialogWrapper: {
padding: theme.spacing(2),
position: "absolute",
top: theme.spacing(5)
},
dialogTitle: {
paddingRight: 0
},
button: {
margin: theme.spacing(0.5),
textTransform: "none"
},
buttonsContainer: {
display: "flex",
flex: "0 0 auto",
justifyContent: "flex-end",
width: "100%",
height: "100%"
},
buttons: {
display: "flex"
}
}));
function Popup(props) {
const classes = useStyles();
const { title, children, openPopup, setOpenPopup, ...rest } = props;
return (
<Dialog
{...rest}
open={openPopup}
maxWidth="sm"
classes={{ paper: classes.dialogWrapper }}
>
<DialogTitle dividers="true" className={classes.dialogTitle}>
<div style={{ display: "flex" }}>
<Typography variant="h4" component="div" style={{ flexGrow: 1 }}>
Country
</Typography>
</div>
</DialogTitle>
<Divider />
<DialogContent direction="row">{children}</DialogContent>
<DialogActions>
<Grid container className={classes.buttonsContainer}>
<Box className={classes.buttons}>
<Button
className={classes.button}
variant="contained"
color="primary"
type="submit"
form="form"
>
Save
</Button>
<Button
className={classes.button}
color="default"
fullWidth
onClick={() => {
setOpenPopup(false);
}}
>
Cancel
</Button>
</Box>
</Grid>
</DialogActions>
</Dialog>
);
}
export default Popup;
Print submiting
我把代码放在沙箱里: https://codesandbox.io/s/react-list-modal-form-qzn2b
谢谢你的帮助!
您可以使用 Popup 包装通过 Formik 呈现的表单,而不是用 Popup 包装整个 CountryForm,这样做我们现在将能够访问 Formik 提供的 isSubmitting
道具。
<Formik
enableReinitialize={true}
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={_onSubmit}
>
{({ errors, touched, isSubmitting }) => {
return (
<Popup
openPopup={openPopup}
setOpenPopup={setOpenPopup}
disableSave={isSubmitting}
>
<Form id="form">
<Grid container direction="row">
<Grid className={classes.itemGrid} item xs={12}>
<Field
name="abbreviation"
label="Abbreviation"
margin="dense"
variant="outlined"
disabled={isSubmitting}
component={TextField}
/>
</Grid>
<Grid className={classes.itemGrid} item xs={12}>
<Field
name="name"
type="text"
fullWidth
label="Name"
margin="dense"
variant="outlined"
disabled={isSubmitting}
component={TextField}
/>
</Grid>
</Grid>
</Form>
</Popup>
);
}}
</Formik>