首页 > 解决方案 > 如何在表单为子 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;

打印提交

我把代码放在沙箱里: https ://codesandbox.io/s/react-list-modal-form-qzn2b

我感谢您的帮助!

标签: javascriptreactjsmaterial-uiformikyup

解决方案


您可以使用 Popup 包装通过 Formik 呈现的 Form,而不是使用 Popup 包装整个 CountryForm,这样做我们现在将能够访问isSubmittingFormik 提供的道具。

<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>

工作沙箱


推荐阅读