1

In the Grommet FormField documentation, it states under Component;

The component may be custom as long it supports the properties of name, value, onChange (event => {}), while event has either event.value or event.target.value.

I'd like to implement a custom component but don't understand how it needs to interact with a controlled Form component to supply its value property. Is there an example somewhere that shows how to implement a custom component in a FormField?

010
  • 13
  • 1
  • 3

1 Answers1

1

Here is a code example of Controlled Form that is using a custom input component. I used a plain input tag since it supports the docs specification as mentioned above

...it supports the properties of name, value, onChange (event => {}), while event has either event.value or event.target.value.

However, you can feel free to use your own input component implementation using the template example below. The value of the input will be communicated to the controlled Form without extra coding. Run the following and check out the console logs to see how the value is being updated as you type in the custom input.

import React, { useState } from "react";
import { render } from "react-dom";

import { Box, Button, Form, FormField, Grommet, TextInput } from "grommet";
import { grommet } from "grommet/themes";

const defaultValue = {
  name: "",
  custom: ""
};

export const App = () => {
  const [value, setValue] = useState(defaultValue);
  return (
    <Grommet full theme={grommet}>
      <Box fill align="center" justify="center">
        <Box width="medium">
          <Form
            value={value}
            onChange={(nextValue, { touched }) => {
              console.log("Change", nextValue, touched);
              setValue(nextValue);
            }}
            onSubmit={(event) =>
              console.log("Submit", event.value, event.touched)
            }
          >
            <FormField label="TextInput Field" name="name">
              <TextInput name="name" />
            </FormField>
            <FormField
              label="Custom Component Field"
              name="custom"
              component={(props) => <input {...props} />} // custom component
            />

            <Box direction="row" justify="between" margin={{ top: "medium" }}>
              <Button type="submit" label="Update" primary />
            </Box>
          </Form>
        </Box>
      </Box>
    </Grommet>
  );
};

render(<App />, document.getElementById("root"));

Shimi
  • 1,178
  • 8
  • 18
  • thank you for the detailed response; I really appreciate it. If we wanted to use a non-standard component that doesn't automatically integrate like an input component, like for example a CAPTCHA component, how does it communicate the required properties (onChange, value etc) back to the form? Apologies in advance; I've looked at the source of both Form & FormField and still don't understand the voodoo involved. – 010 May 15 '21 at 00:06
  • The magic is within both react and grommet so you won't necessarily find it on the Grommet code. If your Captcha component is implemented using the input tag at its core, it should work as well. Give it a try and share your results. – Shimi May 15 '21 at 13:08
  • Google's reCaptcha uses a hidden Textarea, which doesn't appear to trigger the Grommet Form's onChange event. I also tried adding a hidden input and setting its value when the Captcha completes; even that does not trigger the onChange event of the Form. – 010 May 15 '21 at 21:35
  • Feel free to share a code example of what you are trying to achieve – Shimi May 19 '21 at 03:01
  • The goal is to have the FormField's validate method fire when the captcha completes, and ultimately have the Form's validate method fire. There's nothing more to the code than adding Google's recaptcha component as a child to a FormField. Everything I've tried has not yielded the desired result. – 010 May 19 '21 at 07:06