Using Controller component from react-hook-form

Hi there, I’m wondering what is the correct way to get a controller component working with redwood forms.

I feel like I have everything setup right but I can not get the controller to register and I’m not seeing any data.

Here is my code

import { useForm, Controller } from 'react-hook-form'
import Select from 'react-select/creatable'

export const QUERY = gql`
  query FindPlants {
    plants {
      id
      title
    }
  }
`

export const Loading = () => <div>Loading...</div>

export const Empty = () => <div>Empty</div>

export const Failure = ({ error }) => (
  <div style={{ color: 'red' }}>Error: {error.message}</div>
)

export const Success = ({ plants }) => {
  const methods = useForm()

  return (
    <Controller
      control={methods.control}
      defaultValue={[]}
      name="field_name_product"
      render={({ field }) => {
        console.log(field)
        const { onChange, value, name, ref } = field
        return (
          <Select
            name={name}
            inputRef={ref}
            options={plants}
            value={plants.find((c) => c.id === value)}
            onChange={(val) => {
              onChange(val)
            }}
            getOptionValue={(option) => option.id}
            getOptionLabel={(option) => option.title}
            className="basic-multi-select"
            classNamePrefix="select"
            isMulti
          />
        )
      }}
    />
  )
}

I’m importing this into a standard redwood form, but the data is never submitted.

I have also tried putting the controller component directly in the form and that did not work either

Do i need to register or something?

Thanks
Shannon

Hi Shannon! Welcome to the Redwood community!

If I understand your problem correctly, when you submit with form the Controller there’s no data. Is that right?

Only thing I’d change is to wrap with <form>. Something like this:

<form onSubmit={methods.handleSubmit((data) => console.log(data))}>
  // <Your Controller magic here>
  <button type="submit">Submit</button>
</form>

Here’s a short tape to show you what I’m seeing: https://s.tape.sh/R7uB0cmD
Here’s the full code of the cell in this tape: https://gist.github.com/callingmedic911/07ffe53217a09339c842f631c9e084ac

Here’s an example from react-hook-forms using react-select: https://react-hook-form.com/get-started/#integratingwithuilibraries

Let me know if missed anything. I’d be glad to help. :slight_smile:

Thanks for the quick reply. The issue I am having is more around using the controller in an existing redwood form.

Here is a quick loom video to show the problem Loom | Free Screen & Video Recording Software

And some more complete code here:

import {
  Form,
  FormError,
  FieldError,
  Label,
  TextField,
  Submit,
} from '@redwoodjs/forms'

import { useForm, Controller } from 'react-hook-form'
import Select from 'react-select/creatable'

const NoteForm = (props) => {
  const options = [
    { id: 1, title: 'plant 1' },
    { id: 2, title: 'plant 2' },
  ]

  const methods = useForm()

  const onSubmit = (data) => {
    console.log(data)
    props.onSave(data, props?.note?.id)
  }

  return (
    <div className="rw-form-wrapper">
      <Form
        onSubmit={onSubmit}
        // onSubmit={methods.handleSubmit((data) =>
        //     console.log('data-----', data)
        //   )}
        error={props.error}
      >
        <FormError
          error={props.error}
          wrapperClassName="rw-form-error-wrapper"
          titleClassName="rw-form-error-title"
          listClassName="rw-form-error-list"
        />

        <Label
          name="description"
          className="rw-label"
          errorClassName="rw-label rw-label-error"
        >
          Description
        </Label>
        <TextField
          name="description"
          defaultValue={props.note?.description}
          className="rw-input"
          errorClassName="rw-input rw-input-error"
          validation={{ required: true }}
        />

        <FieldError name="description" className="rw-field-error" />

        {/* <PlantSelectCell /> */}

        <Controller
          control={methods.control}
          defaultValue={[]}
          name="field_name_product"
          render={({ field }) => {
            console.log(field)
            const { onChange, value, name, ref } = field
            return (
              <Select
                name={name}
                inputRef={ref}
                options={options}
                value={options.find((c) => c.id === value)}
                onChange={(val) => {
                  onChange(val)
                }}
                getOptionValue={(option) => option.id}
                getOptionLabel={(option) => option.title}
                className="basic-multi-select"
                classNamePrefix="select"
                isMulti
              />
            )
          }}
        />

        <div className="rw-button-group">
          <Submit disabled={props.loading} className="rw-button rw-button-blue">
            Save
          </Submit>
        </div>
      </Form>
    </div>
  )
}

export default NoteForm

Got it! Thanks for the detailed explanation.

I think the Form and the Controller within are referring to the different useForm() instance. Since Redwood form uses FormProvider, you can get rid of useForm in the cell and remove the prop control from the Controller.

Let me know if this resolves your issue.

Perfect Thanks so much @callingmedic911

1 Like