Chakra UI with 'redwoodjs/forms' elements

*The Chakra docs describe how to set isValid=false and display the FormErrorMessage. However, afaics, one of the downsides of their implementation is that the errorBorderColor is displayed when the form loads. To work around this I added an onClick function to the Submit button. (Code below for anyone who’s interested. If there are better ways to do this, would love to hear.)

Re: the some of the examples above, it looks as though the client & server side message fields are being conflated. Linking to the redwood docs for clarification.

<FormError> Displays error messages from the server. Typically placed at the top of your form

<FieldError> Displays error messages if the field with the same name prop has validation errors. Only renders if there’s an error on the associated field


The following now works well for me for client side validations:

  const [emailError, setEmailError] = useBoolean(false)
  const [emailValue, setEmailValue] = useState('')
  const handleInputChange = (e) => setEmailValue(e.target.value)

  const onSubmit = (data: FormEvent) => {
    props.onSave(data, props?.event?.id)
  }

  const onClick = () => {
    if (emailValue === '') setEmailError.toggle()
  }

...

<FormControl isInvalid={emailError}>
  <FormLabel htmlFor="email">Email address</FormLabel>
  <Input
    as={TextField}
    name="email"
    value={emailValue}
    focusBorderColor={eventColorScheme}
    errorBorderColor={
      emailValue === '' && emailError ? 'red.300' : 'inherit'
    }
    placeholder="Email address"
    onChange={handleInputChange}
    validation={{
      required: {
        value: true,
        message: 'Email is required',
      },
    }}
  />
  {!emailError ? (
    <FormHelperText>Some help text when no error</FormHelperText>
  ) : (
    <FormErrorMessage as={FieldError} name="email" />
  )}
</FormControl>

<Flex justify="space-between" mt="10">
  <Spacer />
  <Button colorScheme={eventColorScheme}>
    <Submit disabled={props.loading} onClick={onClick}>
      Submit
    </Submit>
  </Button>
</Flex>

I have an action to no-longer wrap Submit in Button but it works for now.

Havent seen it in the replies, but I used redwoods useForm hook to track errors. It can be easily combined with chakras FormControls as well as FormErrorMessage. Furthermore as we have seen above, the “as” prop is awesome chakra magic, allowing us to style redwoods components. Just does not work with but thats not a problem.

Here is the code (might not be fully working). Submit function is i.e. missing, since my form was login form, which works a bit different than other redwood forms:

const MyForm = () =>{
  const formMethods = useForm()

  
   return <Form formMethods={formMethods} onSubmit={onSubmit}>
  <FormControl
                    isInvalid={
                      formMethods.formState.errors.username ? true : false
                    }
                  >
                    <FormLabel as={Label} name="username">
                      Email
                    </FormLabel>
                    <Input
                      as={TextField}
                      name="username"
                      autoComplete="username"
                      validation={{
                        required: {
                          value: true,
                          message: 'Username is required',
                        },
                      }}
                    />

                    {!formMethods.formState.errors.username ? (
                      <FormHelperText>
                        Enter Username
                      </FormHelperText>
                    ) : (
                      <FormErrorMessage>
                        <FieldError name="username" />
                      </FormErrorMessage>
                    )}
                  </FormControl>
              <Button type="submit">Submit</Button>
</Form>
}
3 Likes

This solution seems to be the most succint way of pulling this off without losing any of the styling of Chakra or the benefits of Redwood. Thank you for posting this!

1 Like