formik-material-ui 不适用于 TogglleButtonGroup 组件

Posted

技术标签:

【中文标题】formik-material-ui 不适用于 TogglleButtonGroup 组件【英文标题】:formik-material-ui not working for TogglleButtonGroup Component 【发布时间】:2020-09-29 23:24:11 【问题描述】:

在我的 React 代码中,连同其他输入类型,我还必须使用 material-ui 的 ToggleButtonGroup 组件。 formik-material-ui 不直接支持该组件,我一直在尝试编写自定义包装器,但没有取得多大成功。这就是我的组件的外观(formikToggleButtonGroup.tsx):

import * as React from 'react';
import MuiToggleButtonGroup, 
  ToggleButtonGroupProps as MuiToggleButtonGroupProps,
 from '@material-ui/lab/ToggleButtonGroup';
import  FieldProps  from 'formik';

export interface ToggleButtonGroupProps
  extends FieldProps,
    Omit<MuiToggleButtonGroupProps, 'name' | 'value'> 

export function fieldToToggleButtonGroup(
  field,
  // Exclude Form
  form,
  ...props
: ToggleButtonGroupProps): MuiToggleButtonGroupProps 
  return 
    ...props,
    ...field,
  ;


export default function ToggleButtonGroup(props: ToggleButtonGroupProps) 
  return <MuiToggleButtonGroup ...fieldToToggleButtonGroup(props) />;

ToggleButtonGroup.displayName = 'FormikMaterialUIToggleButtonGroup';`

然后,我尝试像这样使用它:

import Layout from '../../components/layout'
import Header from '../../components/header'
import ToggleButtonGroup from '../../components/formikToggleButtonGroup.tsx'
import React,  useState  from 'react';
import  makeStyles  from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
import Container from '@material-ui/core/Container';
import CssBaseline from '@material-ui/core/CssBaseline';
import Grid from '@material-ui/core/Grid';
import Box from '@material-ui/core/Box';
import ToggleButton from '@material-ui/lab/ToggleButton';
import  withStyles  from '@material-ui/core/styles';
import  green, orange  from '@material-ui/core/colors';
import Radio from '@material-ui/core/Radio';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import FormControl from '@material-ui/core/FormControl';
import FormLabel from '@material-ui/core/FormLabel';
import * as Yup from "yup";
import  Formik, Form, Field from 'formik';
import  TextField, RadioGroup  from 'formik-material-ui';
import ToggleButtonGroup from '../../components/formikToggleButtonGroup.tsx'
import ToggleButton from '@material-ui/lab/ToggleButton';

const StyledButton = withStyles((theme)=>(
  root: 
    background: theme.palette.background.paper,
    color: theme.palette.text.primary,
    marginBottom: theme.spacing(3),
    marginRight: theme.spacing(4),
    borderRadius: '0',
    borderWidth: '1px',
    borderColor: theme.palette.divider,
    borderLeft:'1px solid rgba(0, 0, 0, 0.12) !important',
    padding: '0 30px',
    fontSize:'0.7rem',
    fontWeight:'400',
    '&$selected': 
      color: theme.palette.background.default,
      backgroundColor: theme.palette.warning.main,
    ,
    '&:hover': 
      color: theme.palette.background.default,
      backgroundColor: theme.palette.warning.light,
    ,
    '&$selected:hover': 
      color: theme.palette.background.default,
      backgroundColor: theme.palette.warning.light,
    ,
  ,
  selected:
    color: theme.palette.background.default,
    backgroundColor: theme.palette.warning.main,
  ,
  hover:
    color: theme.palette.background.default,
    backgroundColor: theme.palette.warning.light,
  ,
  label: 
    textTransform: 'capitalize',
  ,
))(ToggleButton);

export default function GetUserInfo() 
    const classes = useStyles();
    
    const [selectedValue, setSelectedValue] = useState('yes');

    const handleRadioChange = (event) => 
      setSelectedValue(event.target.value);
    ;

    const handleSubmit = (evt) => 
        evt.preventDefault();
        alert(`Submitting Name $name $phone $email`)
    

    const handleChange = (event, newAlignment) => 
      alert(newAlignment)
      if (newAlignment !== null) 
        setGrade(newAlignment);
      
    ;
    
    return (
      <Layout title="My first Next page" meta_desc="Best online coding classes for kids & children">
        <CssBaseline />
        <Header />
        <Container component="main" >
          <Grid container spacing=4>
            <Grid item xs=12 sm=8 className=classes.boxStyle>
              <Box mx="auto" p=2>
                <Formik
                  initialValues=initialValues
                  validate=
                    values => 
                      const errors = ;
                      if (!values.parentEmail) 
                        errors.parentEmail = 'Required';
                       else if (
                        !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]2,4$/i.test(values.parentEmail)
                      ) 
                        errors.parentEmail = 'Invalid email address';
                       else if (!values.parentName)
                        errors.parentName = 'Required';
                       else if (!values.countryCode)
                        errors.countryCode = 'Required';
                       else if (!values.phone)
                        errors.phone = 'Required';
                       else if (!values.childName)
                        errors.childName = 'Required';
                       else if (!values.grade)
                        errors.grade = 'Required';
                       else if (!values.computer)
                        errors.computer = 'Required';
                      
                      return errors;
                    
                  
                  onSubmit=(values,  setSubmitting ) => 
                    setTimeout(() => 
                      setSubmitting(false);
                      alert(JSON.stringify(values, null, 2));
                    , 500);
                  
                >
                  ( submitForm, isSubmitting ) => (
                    <Form className=classes.root autoComplete="off">
                        <Box>
                          <Field 
                            component=TextField 
                            fullWidth 
                            name="childName" 
                            onChange=e => setChildName(e.target.value) 
                            required id="standard-required" label="Kid's Name"
                            helperText="Certificate will be issued with this name"/>
                        </Box>
                        <Box mt=3 className=classes.labelFont>
                          Kid's Grade?
                        </Box>
                        <Box mt=2>
                          <ToggleButtonGroup
                            component=ToggleButtonGroup
                            mt=7
                            name="grade"
                            //value=grade
                            exclusive="true"
                            //onChange=handleChange
                            aria-label="text alignment"
                          >
                            <StyledButton className=classes.buttonMargin 
                              value="1" aria-label="left aligned">
                              <label class="btn btn-secondary m-2 rounded">
                                Grade <br/> <strong>1 - 3</strong>
                              </label>
                            </StyledButton>
                            <StyledButton className=classes.buttonMargin value="2" aria-label="centered">
                              <label class="btn btn-secondary m-2 rounded ">
                                Grade <br/> <strong>4 - 6</strong>
                              </label>
                            </StyledButton>
                            <StyledButton className=classes.buttonMargin value="3" aria-label="right aligned">
                              <label class="btn btn-secondary m-2 rounded">
                              Grade <br/> <strong>7 - 9</strong>
                              </label>
                            </StyledButton>
                            <StyledButton className=classes.buttonMargin value="4" aria-label="justified">
                              <label class="btn btn-secondary m-2 rounded">
                              Grade <br/><strong>10 - 12</strong>
                              </label>
                            </StyledButton>
                          </ToggleButtonGroup>
                        </Box>
                        <Button
                        disabled=isSubmitting
                        onClick=submitForm
                        //type="submit"
                        //onClick=handleSubmit
                        fullWidth
                        variant="contained"
                        color="primary"
                        className=classes.submit>Let's Start
                        </Button>
                      </Form>
                  )
                  </Formik>
                </Box>
            </Grid>
     
          </Grid>
        </Container>
      </Layout>
    )
  

我面临的问题是 Formik 没有设置 ToggleButtonGroup 的值。它总是显示初始值。

【问题讨论】:

【参考方案1】:

通过手动处理 onChange 事件并手动更新 formik 实例,我能够使 formikToggleButtonGroup 一起工作:

export default function MyComponent() 

  const formik = useFormik(
    initialValues: 
      roleType: 0,
    ,
    onSubmit: async (values) => 
       // send ajax request
    ,
  );

  // handler for ToggleButtonGroup
  const handleRoleChange = (event: any, role: string) => 
    // manually update formik
    formik.setFieldValue('roleType', role);
  ;

  return (
        <form noValidate onSubmit=formik.handleSubmit>
          <ToggleButtonGroup
            exclusive
            id="roleType"
            value=formik.values.roleType
            onChange=handleRoleChange
          >
            <ToggleButton value=0>
              <PersonIcon />
              <div>Role 1</div>
            </ToggleButton>
            <ToggleButton value=1>
              <RestaurantIcon />
              <div>Role 2</div>
            </ToggleButton>
          </ToggleButtonGroup>
          <Button type="submit">
            Submit
          </Button>
        </form>
  );

【讨论】:

以上是关于formik-material-ui 不适用于 TogglleButtonGroup 组件的主要内容,如果未能解决你的问题,请参考以下文章

更新事件不适用于 EWS 访问被拒绝

Android 房间 DAO 接口不适用于继承

Ccache 不适用于 gcc -M 标志?

计算的 vue js 不适用于惯性

AS 兼容性:“.. from T as a..”适用于 MySQL 和 SQL Server,而不适用于 Oracle? [复制]

分页列表不适用于具有多个模型的视图