Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

<Field /> component with type {CheckboxWithLabel} kills Chrome's autofill functionality #304

Open
lunule opened this issue Nov 27, 2021 · 0 comments
Labels
bug Something isn't working

Comments

@lunule
Copy link

lunule commented Nov 27, 2021

Current Behavior 馃槸

If a Field with type {CheckboxWithLabel} is used, it kills Chrome's autofill functionality. Fields before the checkbox lose autofill.
Actually, I'm not sure if this is a MUI, a formik-mui or a Formik bug, but, as I tested it mostly with the Field component and with a formik-mui component type, I submit the bug report here.

Everything I use is the of latest version: formik-mui: 4.0.0-alpha.2, MUI 5.2.1, Formik 2.2.9.

Expected Behavior 馃

Well, obviously, the expected behaviour is components not killing a must-have functionality of the most popular browser. :)

Steps to Reproduce 馃暪

All I can add here is the code I actually have:

import logo from './logo.svg';
import './App.css';
import React, {useState} from 'react';
import { Field, Form, Formik, FormikConfig, FormikValues, useFormik } from 'formik';
import { mixed, number, object } from 'yup';

import { Box, Button, Card, CardContent, CircularProgress, Grid, Step, StepLabel, Stepper, Typography, Slider } from '@mui/material';
import { spacing } from '@mui/system';
import { CheckboxWithLabel, TextField, Checkbox } from 'formik-mui';

import { experimentalStyled as styled, createTheme, ThemeProvider } from "@mui/material/styles";
import { blue, grey } from '@mui/material/colors';
import CssBaseline from '@mui/material/CssBaseline';

const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

const CustomizedSlider = styled(Slider)`
  color: #20b2aa;

  transition: all .2s ease-in-out;

  :hover {
    color: #2e8b57;
  }
`;

const theme = createTheme({
  spacing: 8,
  palette: {
    primary: blue,
    background: {
      paper: '#f6f6f6',
    },    
  },  
})

const lightGrey = grey[100];

export default function App() {

  const formik = useFormik({
    initialValues: {
      kmpFieldEmail: '[email protected]', 
      kmpFieldName: '', 
      kmpFieldNewsletter: true, 
    },
    onSubmit: async values => {

      await sleep(2000);
      alert(JSON.stringify(values, null, 2));

    },
  });

    return (
      <ThemeProvider theme={theme}>
        <Card sx={{bgcolor: 'background.paper'}}>
            <CardContent>
              <FormikStepper
                initialValues={formik.values}
                onSubmit={formik.handleSubmit}
              >
                  <FormikStep label="Personal Details">
                
              <Box sx={{pb:2}}>
                <Field 
                  fullwidth 
                  type="text"
                  name="kmpFieldName" 
                  component={TextField} 
                  label="Name" 
                  inputProps={{ onChange:formik.handleChange }}
                  value={formik.values.kmpFieldName}
                  placeholder=""
                />
              </Box>

              <Box sx={{pb:2}}>
                <Field 
                  fullwidth 
                  type="email"
                  name="kmpFieldEmail" 
                  component={TextField} 
                  label="Email" 
                  inputProps={{ onChange:formik.handleChange }}
                  value={formik.values.kmpFieldEmail}
                  placeholder=""
                />
              </Box>

       <label htmlFor="email">Email Address</label>
       <input
         id="email"
         name="email"
         type="text"
         style={{display:'none'}}
       />              

              <Box sx={{pb:2}}>
                <Field  
                  type="checkbox"
                  name="kmpFieldNewsletter" 
                  component={CheckboxWithLabel} 
                  Label={{ label: 'Yes, I want to subscribe' }} 
                  inputProps={{ onChange:formik.handleChange }}
                  checked={formik.values.kmpFieldNewsletter == true ? true : false}
                />
              </Box>                

                  </FormikStep>
              
                  <FormikStep
                    label="Calorie Information"
                    validationSchema={object({
                        money: mixed().when('millionaire', {
                          is: true,
                          then: number()
                            .required()
                            .min(
                              1_000_000,
                              'Because you said you are a millionaire you need to have 1 million'
                            ),
                          otherwise: number().required(),
                        }),
                    })}
                  >

              <Box sx={{pb:2}}>
                
                    <Typography id="kmp-label--calorie-slider" gutterBottom>
                      Select how many calories you鈥檇 like your interactive sliding meal plan to follow:
                    </Typography>               

                <CustomizedSlider
                    aria-label="Calorie Target"
                    defaultValue={1800}
                    valueLabelDisplay="auto"
                    step={100}
                    marks
                    min={1200}
                    max={2500}
                />

                    <Typography id="kmp-sublabel--calorie-slider" gutterBottom>
                  Need help? Visit our <a href="/calculator/" target="_blank">Keto Calculator</a>.
                </Typography>

              </Box>

                  </FormikStep>

                  <FormikStep
                    label="Personal Preferences"
                  >

              <Box sx={{pb:2}}>
                
                <Field 
                  fullwidth 
                  type="email"
                  name="kmpFieldEmail" 
                  component={TextField} 
                  label="Email" 
                  //inputProps={{ onChange:props.handleChange }}
                  placeholder=""
                />

              </Box>

                  </FormikStep>                 

              </FormikStepper>

          </CardContent>
      </Card>
    </ThemeProvider>
  );
}

export interface FormikStepProps
  extends Pick<FormikConfig<FormikValues>, 'children' | 'validationSchema'> {
  label: string;
}

export function FormikStep({ children }: FormikStepProps) {
  return <>{children}</>;
}

export function FormikStepper({ children, ...props }: FormikConfig<FormikValues>) {
  const childrenArray = React.Children.toArray(children) as React.ReactElement<FormikStepProps>[];
  const [step, setStep] = useState(0);
  const currentChild = childrenArray[step];
  const [completed, setCompleted] = useState(false);

  const alertShit = function() {
    alert('Shit');
  }

  function isLastStep() {
    return step === childrenArray.length - 1;
  }

  return (
    <Formik
      {...props}
      validationSchema={currentChild.props.validationSchema}
      onSubmit={async (values, helpers) => {
        if (isLastStep()) {
          await props.onSubmit(values, helpers);
          setCompleted(true);
        } else {
          setStep((s) => s + 1);

          // If you have multiple fields on the same step
          // we will see they show the validation error all at the same time after the first step!
          //
          // If you want to keep that behaviour, then, comment the next line :)
          // If you want the second/third/fourth/etc steps with the same behaviour
          //    as the first step regarding validation errors, then the next line is for you! =)
          helpers.setTouched({});
        }
      }}
    >
      {({ isSubmitting }) => (
        <Form>

          <Stepper 
            alternativeLabel 
            activeStep={step}
            sx={{ mb: 4 }}
          >
        
            {childrenArray.map((child, index) => (
              <Step key={child.props.label} completed={step > index || completed}>
                <StepLabel>{child.props.label}</StepLabel>
              </Step>
            ))}
        
          </Stepper>

          {currentChild}

          <Grid 
            container 
            sx={{mt:4}} 
            justifyContent="space-between"
          >
            {step > 0 ? (
              <Grid item>
                <Button
                  disabled={isSubmitting}
                  variant="contained"
                  color="primary"
                  onClick={() => setStep((s) => s - 1)}
                >
                  Back
                </Button>
              </Grid>
            ) : null}
            <Grid item>
              <Button
                startIcon={isSubmitting ? <CircularProgress size="1rem" /> : null}
                disabled={isSubmitting}
                variant="contained"
                color="primary"
                type="submit"
              >
                {isSubmitting ? 'Submitting' : isLastStep() ? 'Submit' : 'Next'}
              </Button>
            </Grid>
          </Grid>
        </Form>
      )}
    </Formik>
  );
}

This code works - but if you remove the fixing snippet:

 <input
   id="email"
   name="email"
   type="text"
   style={{display:'none'}}
 />      

... then Chrome's autofill doesn't work anymore.

FYKI: the file is typescript (with .tsx extension) - but it doesn't matter. I tested the issue without the stuff written in typescript and the file rebaptised to .js, and the result is the same.

Thanks for investigating this further.

@lunule lunule added the bug Something isn't working label Nov 27, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant