react-hook-form#useFormContext TypeScript Examples

The following examples show how to use react-hook-form#useFormContext. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: util.tsx    From tobira with Apache License 2.0 7 votes vote down vote up
ShowTitle: React.FC<ShowTitleProps> = ({ showTitle }) => {
    const { t } = useTranslation();
    const { register } = useFormContext<ShowTitleProps>();

    return <>
        <Heading>{t("manage.realm.content.titled.title")}</Heading>
        <label>
            <input type="checkbox" defaultChecked={showTitle} {...register("showTitle")} />
            {t("manage.realm.content.titled.show-title")}
        </label>
    </>;
}
Example #2
Source File: useSubmitVariantNameForm.ts    From calories-in with MIT License 6 votes vote down vote up
function useSubmitVariantNameForm({ onComplete, variantFormIndex }: Params) {
  const dietFormActions = useDietFormActions()
  const { handleSubmit } = useFormContext()

  const onSubmit = handleSubmit((form: VariantNameForm) => {
    onComplete(form)

    dietFormActions.updateVariantForm(variantFormIndex, { name: form.name })
  })

  return onSubmit
}
Example #3
Source File: FormCard.tsx    From rn-credit-card with MIT License 6 votes vote down vote up
FormCard: React.FC<Props> = ({ cardType, focusedField }) => {
  const { watch } = useFormContext()
  const model = watch()

  return (
    <Card
      cardType={cardType}
      focusedField={focusedField}
      model={{
        cardNumber: model.cardNumber,
        expiration: model.expiration,
        holderName: model.holderName,
        cvv: model.cvv,
      }}
    />
  )
}
Example #4
Source File: pricing-form-context.tsx    From admin with MIT License 6 votes vote down vote up
usePriceListForm = () => {
  const context = React.useContext(PriceListFormContext)
  const form = useFormContext()
  if (context === null) {
    throw new Error(
      "usePriceListForm must be used within a PriceListFormProvider"
    )
  }
  return { ...form, ...context }
}
Example #5
Source File: SortRadioGroup.tsx    From firebase-tools-ui with Apache License 2.0 6 votes vote down vote up
SortRadioGroup: React.FC<
  React.PropsWithChildren<{ name: string; disabled: boolean }>
> = ({ name, disabled }) => {
  const { register, setValue, unregister, watch } = useFormContext();

  useEffect(() => {
    if (!disabled) {
      register(name);
    } else {
      setValue(name, undefined);
    }

    return () => unregister(name);
  }, [register, unregister, disabled, name, setValue]);

  const sort = watch(name);

  return (
    <>
      <Radio
        value="asc"
        label="Ascending"
        checked={sort === 'asc'}
        onChange={() => setValue(name, 'asc')}
        disabled={disabled}
      />

      <Radio
        value="desc"
        label="Descending"
        checked={sort === 'desc'}
        onChange={() => setValue(name, 'desc')}
        disabled={disabled}
      />
    </>
  );
}
Example #6
Source File: registerAddToCartButton.tsx    From plasmic with MIT License 6 votes vote down vote up
export function AddToCartButton(props: AddToCartButtonProps) {
  const { children } = props;

  const product = useProduct();
  const form = useFormContext();
  const addItem = useAddItem();

  const addToCart = async() => {
    const quantity = +(form.getValues()["ProductQuantity"] ?? 1);
    if (isNaN(quantity) || quantity < 1) {
      throw new CommerceError({
        message: 'The item quantity has to be a valid integer greater than 0',
      })
    }
    if (product) {
      const variantId = form.getValues()["ProductVariant"] ?? product.variants[0].id;
      await addItem({
        productId: product.id,
        variantId: variantId,
        quantity: quantity
      })
    }
  }

  return (
    React.isValidElement(children)
      ? React.cloneElement(children, {
          onClick: (e: MouseEvent) => {
            if (children.props.onClick && typeof children.props.onClick === "function") {
              children.props.onClick(e);
            }
            addToCart();
          }
        })
      : null
  )
}
Example #7
Source File: ConditionEntries.tsx    From firebase-tools-ui with Apache License 2.0 6 votes vote down vote up
ConditionEntries: React.FC<
  React.PropsWithChildren<{ name: string }>
> = ({ name }) => {
  const {
    formState: { errors, touchedFields },
  } = useFormContext();

  const { fields, append, remove } = useFieldArray({
    name,
  });

  useEffect(() => {
    if (fields.length < 1) {
      append('');
    }
  }, [append, fields]);

  return (
    <ul className={styles.conditionEntries}>
      {fields.map((field, index) => {
        const conditionName = `${name}[${index}]`;
        return (
          <li key={field.id}>
            <ConditionEntry
              name={conditionName}
              error={touchedFields[conditionName] && errors[conditionName]}
            />
            <IconButton
              className={
                fields.length > 1 ? styles.removeFilter : styles.hidden
              }
              icon="delete"
              label="Remove filter"
              type="button"
              onClick={() => remove(index)}
            />
          </li>
        );
      })}
      <Button type="button" icon="add" onClick={() => append('')}>
        Add value
      </Button>
    </ul>
  );
}
Example #8
Source File: index.tsx    From tobira with Apache License 2.0 6 votes vote down vote up
EditModeButtons: React.FC<EditModeButtonsProps> = ({ onCancel }) => {
    const { t } = useTranslation();

    const modalRef = useRef<ConfirmationModalHandle>(null);

    const { formState: { isDirty } } = useFormContext();

    return <div css={{
        marginTop: 8,
        display: "flex",
        justifyContent: "space-between",
    }}>
        <Button
            kind="danger"
            onClick={() => {
                if (isDirty) {
                    currentRef(modalRef).open();
                } else {
                    onCancel?.();
                }
            }}
        >
            {t("manage.realm.content.cancel")}
        </Button>
        <Button
            kind="happy"
            type="submit"
        >
            {t("manage.realm.content.save")}
        </Button>
        <ConfirmationModal
            buttonContent={t("manage.realm.content.cancel")}
            onSubmit={onCancel}
            ref={modalRef}
        >
            <p>{t("manage.realm.content.cancel-warning")}</p>
        </ConfirmationModal>
    </div>;
}
Example #9
Source File: registerProductPrice.tsx    From plasmic with MIT License 6 votes vote down vote up
export function ProductPriceComponent(props: ProductPriceProps) {
  const { className } = props;

  const product = useProduct();
  const form = useFormContext();

  const watchProductVariant = form?.watch(
    "ProductVariant",
    product.price ?? ""
  );

  const { price } = usePrice({
    amount: product ? getProductPrice(product, watchProductVariant) : 0,
    currencyCode: product ? product.price.currencyCode! : "USD",
  });

  return <span className={className}>{price}</span>;
}
Example #10
Source File: CalculatorActivitiesSection.tsx    From po8klasie with GNU General Public License v3.0 6 votes vote down vote up
CalculatorActivitiesSection: FC<CalculatorActivitiesSectionProps> = ({
  checkboxesData,
  sectionPoints,
}) => {
  const { register } = useFormContext();
  return (
    <div className="m-5">
      <h3 className="text-2xl font-bold mb-3">Osiągnięcia</h3>
      <div data-testid="checkboxes">
        {checkboxesData.map(({ id, name }) => (
          <ActivityCheckbox
            key={id}
            name={name}
            inputProps={register(id)}
            calculatedPoints={sectionPoints[id] as number}
          />
        ))}
      </div>
      <h4 className="text-xl font-bold mt-5">Konkursy</h4>
      <span className="inline-block rounded-full bg-light text-black uppercase px-2 py-1 text-xs mt-2 font-bold">
        Wkrótce
      </span>
    </div>
  );
}
Example #11
Source File: Step3.tsx    From frontend with GNU General Public License v3.0 6 votes vote down vote up
Step3 = (): JSX.Element => {
  const { register, errors } = useFormContext();

  const { fivestep, sixstep } = useSelector((state: RootState) => state.multiStepExample);

  return (
    <div>
      <Input
        label="test"
        placeholder="test"
        name="fivestep"
        defaultValue={fivestep}
        ref={register({ required: 'this is required' })}
        error={errors.fivestep?.message}
        fullWidth
      />
      <Input
        label="test"
        placeholder="test"
        name="sixstep"
        defaultValue={sixstep}
        ref={register({ required: 'this is required' })}
        error={errors.sixstep?.message}
        fullWidth
      />
    </div>
  );
}
Example #12
Source File: useVariantFormEvents.ts    From calories-in with MIT License 6 votes vote down vote up
function useVariantFormEvents({ dietFormStatsTree }: Params) {
  const { reset } = useFormContext()
  const variantFormFieldId = useWatch({ name: 'variantFormFieldId' })

  function getVariantStatsForForFieldId(value: string) {
    if (value) {
      const stats = dietFormStatsTree.subtrees.find(({ id }) => id === value)

      if (!stats) {
        throw new Error()
      }

      return stats.stats
    }

    return dietFormStatsTree.avg as Stats
  }

  const variantStats = getVariantStatsForForFieldId(variantFormFieldId)

  function onVariantFormFieldIdChange(value: string) {
    const variantStats = getVariantStatsForForFieldId(value)
    const newVaraintsDetailsForm = getVariantsDetailsForm(value, variantStats)
    reset(newVaraintsDetailsForm)
  }

  return { onVariantFormFieldIdChange, variantStats }
}
Example #13
Source File: LabeledRadio.tsx    From UsTaxes with GNU Affero General Public License v3.0 6 votes vote down vote up
export function LabeledRadio<A>(props: LabeledRadioProps<A>): ReactElement {
  const { label, name, values, useGrid = true, sizes = { xs: 12 } } = props

  const classes = useStyles()
  const { control } = useFormContext<A>()

  return (
    <ConditionallyWrap
      condition={useGrid}
      wrapper={(children) => (
        <Grid item {...sizes}>
          {children}
        </Grid>
      )}
    >
      <Controller
        name={name}
        render={({ field: { value, onChange } }) => (
          <div className={classes.root}>
            <FormControl component="fieldset">
              <FormLabel>{label}</FormLabel>
              <RadioGroup name={name} value={value} onChange={onChange}>
                {values.map(([rowLabel, rowValue], i) => (
                  <FormControlLabel
                    key={i}
                    value={rowValue}
                    control={<Radio color="primary" />}
                    label={rowLabel}
                  />
                ))}
              </RadioGroup>
            </FormControl>
          </div>
        )}
        control={control}
      />
    </ConditionallyWrap>
  )
}
Example #14
Source File: CustomFields.stories.tsx    From react-hook-form-generator with MIT License 6 votes vote down vote up
ReactSelectField = ({ name, label, placeholder, options }) => {
  const { control } = useFormContext();

  return (
    <FormControl>
      <FormLabel>{label}</FormLabel>
      <Controller
        name={name}
        control={control}
        as={
          <Select
            placeholder={placeholder}
            options={options}
          />
        }
        onChange={([selected]) => {
          return selected;
        }}
      />
    </FormControl>
  );
}
Example #15
Source File: Step2.tsx    From frontend with GNU General Public License v3.0 6 votes vote down vote up
Step2 = (): JSX.Element => {
  const { register, errors } = useFormContext();

  const { fourstep, threestep } = useSelector((state: RootState) => state.multiStepExample);

  return (
    <div>
      <Input
        label="test"
        placeholder="test"
        name="threestep"
        defaultValue={threestep}
        ref={register({ required: 'this is required' })}
        error={errors.threestep?.message}
        fullWidth
      />
      <Input
        label="test"
        placeholder="test"
        name="fourstep"
        defaultValue={fourstep}
        ref={register({ required: 'this is required' })}
        error={errors.fourstep?.message}
        fullWidth
      />
    </div>
  );
}
Example #16
Source File: index.tsx    From firebase-tools-ui with Apache License 2.0 5 votes vote down vote up
NameEditor: React.FC<
  React.PropsWithChildren<{
    uuid: number;
    field: MapField;
    childId: number;
    readonly: boolean;
  }>
> = ({ uuid, field, childId, readonly }) => {
  const {
    register,
    unregister,
    setValue,
    setError,
    formState: { touchedFields, errors },
    clearErrors,
  } = useFormContext();

  const dispatch = useDispatch();
  const child = field.mapChildren.find((c) => c.uuid === childId);
  if (!child) {
    throw new Error('Tried to render a name-edtior for a non-map-child');
  }

  const formName = `${childId}`;

  const siblingNames = React.useMemo(() => {
    return field.mapChildren
      .filter((c) => c.uuid !== childId)
      .map((c) => c.name);
  }, [field, childId]);

  useEffect(() => {
    register(formName);
    return () => unregister(formName);
  }, [register, unregister, formName]);

  useEffect(() => {
    // Validate `name` when siblings change
    const isUnique = siblingNames.every((name) => name !== child.name);
    if (!child.name) {
      setError(formName, { type: 'required', message: 'Required' });
    } else if (!isUnique) {
      setError(formName, { type: 'unique', message: 'Must be unique' });
    } else {
      clearErrors(formName);
    }
  }, [child, siblingNames, formName, setError, clearErrors]);

  return (
    <Field
      label="Field"
      outlined
      value={child.name}
      disabled={readonly}
      onChange={(e) => {
        setValue(formName, e.currentTarget.value);
        dispatch(
          actions.updateName({
            uuid,
            childId,
            name: e.currentTarget.value,
          })
        );
      }}
      // Show the `unique` error regardless of the field having been
      // touched; in case another field's name was updated to now conflict
      error={
        (touchedFields[formName] || errors[formName]?.type === 'unique') &&
        errors[formName]?.message
      }
    />
  );
}
Example #17
Source File: nested-form.tsx    From admin with MIT License 5 votes vote down vote up
ConnectForm = ({ children }) => {
  const methods = useFormContext()

  return children({ ...methods })
}
Example #18
Source File: Content.tsx    From calories-in with MIT License 5 votes vote down vote up
function Content({ title, onClose, initialRef, variantFormIndex }: Props) {
  const { register } = useFormContext()
  const nameRegister = register('name')
  const nameInputRef = useMergeRefs(nameRegister.ref, initialRef)

  const onSubmit = useSubmitVariantNameForm({
    variantFormIndex,
    onComplete: onClose,
  })

  const { errorMessage, isInvalid } = useFormError('name')

  useSelectInputText(initialRef)

  return (
    <form onSubmit={onSubmit}>
      <ModalContent>
        <ModalHeader>{title}</ModalHeader>
        <ModalCloseButton />

        <ModalBody>
          <FormControl isInvalid={isInvalid}>
            <FormLabel>Name</FormLabel>
            <Input
              autoComplete="off"
              {...nameRegister}
              ref={nameInputRef}
              focusBorderColor={isInvalid ? 'red.500' : undefined}
              placeholder="Enter name"
            />
            <Collapse animateOpacity={true} in={Boolean(errorMessage)}>
              <Box minHeight="21px">
                <FormErrorMessage>{errorMessage}</FormErrorMessage>
              </Box>
            </Collapse>
          </FormControl>
        </ModalBody>

        <ModalFooter>
          <Button mr={3} onClick={onClose}>
            Close
          </Button>
          <Button
            type="submit"
            colorScheme="teal"
            variant="solid"
            onClick={onSubmit}
          >
            Rename
          </Button>
        </ModalFooter>
      </ModalContent>
    </form>
  )
}
Example #19
Source File: product-form-context.tsx    From admin with MIT License 5 votes vote down vote up
useProductForm = () => {
  const context = React.useContext(ProductFormContext)
  const form = useFormContext()
  if (!context) {
    throw new Error("useProductForm must be a child of ProductFormContext")
  }
  return { ...form, ...context }
}
Example #20
Source File: LabeledCheckbox.tsx    From UsTaxes with GNU Affero General Public License v3.0 5 votes vote down vote up
export function LabeledCheckbox<TFormValues>(
  props: LabeledCheckboxProps<TFormValues>
): ReactElement {
  const { label, name, useGrid = true, sizes = { xs: 12 } } = props
  const { control } = useFormContext<TFormValues>()

  return (
    <ConditionallyWrap
      condition={useGrid}
      wrapper={(children) => (
        <Grid item {...sizes}>
          {children}
        </Grid>
      )}
    >
      <Controller
        name={name}
        render={({ field: { value, onChange } }) => (
          <FormControl component="fieldset">
            <FormGroup>
              <FormControlLabel
                control={
                  <Checkbox
                    name={name}
                    checked={value as boolean}
                    onChange={(_, checked) => onChange(checked)}
                    color="primary"
                  />
                }
                label={label}
                value={value}
              />
            </FormGroup>
          </FormControl>
        )}
        control={control}
      />
    </ConditionallyWrap>
  )
}
Example #21
Source File: useGetInputElement.tsx    From calories-in with MIT License 5 votes vote down vote up
function useGetInputElement({
  inputType,
  name,
  isInvalid,
  nutritionValueUnit,
  isReadOnly,
  textInputRef,
  isBold = false,
}: Params) {
  const { register } = useFormContext()
  let result: ReactElement | null = null
  const textInputRegister = register(name)
  const finalTextInputRef = useMergeRefs(textInputRegister.ref, textInputRef)

  if (isReadOnly) {
    result = (
      <ReadOnlyInput
        name={name}
        inputType={inputType}
        nutritionValueUnit={nutritionValueUnit}
        isBold={isBold}
      />
    )
  } else if (inputType === 'text') {
    result = (
      <Input
        autoComplete="off"
        {...textInputRegister}
        ref={finalTextInputRef}
        fontWeight={isBold ? 'semibold' : 'normal'}
        width={{ base: '150px', md: '200px' }}
      />
    )
  } else if (inputType === 'foodCategory') {
    result = (
      <FoodCategoriesSelect
        {...register(name, {
          valueAsNumber: true,
        })}
        width={{ base: '150px', md: '200px' }}
      >
        <option disabled value={undefined}>
          Select category
        </option>
      </FoodCategoriesSelect>
    )
  } else if (inputType === 'nutritionValue') {
    result = (
      <Controller
        name={name}
        render={({ field }) => (
          <AmountInput value={field.value} onChange={field.onChange} />
        )}
      />
    )
  }

  if (!result) {
    throw new Error()
  }

  if (isInvalid) {
    return cloneElement(result, {
      focusBorderColor: 'red.500',
    })
  }

  return result
}
Example #22
Source File: W2JobInfo.tsx    From UsTaxes with GNU Affero General Public License v3.0 5 votes vote down vote up
Box12Data = (): ReactElement => {
  const [editBox12, setEditBox12] = useState(false)

  const { getValues } = useFormContext<IncomeW2UserInput>()

  const { box12 } = getValues()

  const box12Fields = (
    <>
      {enumKeys(W2Box12Code).map((code) => (
        <Fragment key={`box-12-${code}`}>
          <p>
            <strong>Code {code}</strong>: {W2Box12CodeDescriptions[code]}
          </p>
          <LabeledInput
            label={code}
            name={`box12.${code}`}
            patternConfig={Patterns.currency}
            required={false}
          />
        </Fragment>
      ))}
    </>
  )

  const openCloseButton = (
    <Button
      type="button"
      variant="contained"
      color={editBox12 ? 'secondary' : 'default'}
      onClick={() => setEditBox12(!editBox12)}
    >
      {editBox12 ? 'Done' : 'Edit'}
    </Button>
  )

  const box12Data = (
    <ul>
      {enumKeys(W2Box12Code)
        .filter((code) => box12[code] !== undefined)
        .map((code) => (
          <li key={`box-12-data-${code}`}>
            {code}: <Currency plain value={parseFormNumber(box12[code]) ?? 0} />{' '}
            ({W2Box12CodeDescriptions[code]})
          </li>
        ))}
    </ul>
  )

  return (
    <Paper>
      <Box padding={2} paddingTop={2}>
        <h4>Box 12 Information</h4>
        {editBox12 ? box12Fields : box12Data}
        <Box paddingTop={1}>{openCloseButton}</Box>
      </Box>
    </Paper>
  )
}
Example #23
Source File: index.tsx    From calories-in with MIT License 5 votes vote down vote up
function Tabs({
  nameInputRef,
  food,
  isEditing,
  selectedTabName,
  tabNames,
  onTabNameChange,
}: Props) {
  const { formState } = useFormContext()
  const tabIndex = tabNames.indexOf(selectedTabName)

  function onTabIndexChange(index: number) {
    onTabNameChange(tabNames[index])
  }

  return (
    <TabsBase
      variant="enclosed"
      colorScheme="teal"
      index={tabIndex}
      onChange={onTabIndexChange}
    >
      <TabList>
        <Tab color={formState.errors?.energy ? 'red.500' : undefined}>
          Nutrition Facts
        </Tab>

        {tabNames.includes('volume') && <Tab>Volume</Tab>}
        {tabNames.includes('link') && <Tab>Link</Tab>}
      </TabList>

      <TabPanels>
        <TabPanel px={0}>
          <NutritionFactsFormFields
            nameInputRef={nameInputRef}
            canEdit={isEditing}
          />
        </TabPanel>
        {tabNames.includes('volume') && (
          <TabPanel px={0}>
            <VolumeFormFields food={food} canEdit={isEditing} />
          </TabPanel>
        )}

        {tabNames.includes('link') && (
          <TabPanel px={0}>
            <UrlField canEdit={isEditing} food={food} />
          </TabPanel>
        )}
      </TabPanels>
    </TabsBase>
  )
}
Example #24
Source File: FormContainer.tsx    From UsTaxes with GNU Affero General Public License v3.0 5 votes vote down vote up
OpenableFormContainer = <A,>(
  props: PropsWithChildren<OpenableFormContainerProps<A>>
): ReactElement => {
  const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)')
  const { isOpen = false, allowAdd = true, defaultValues } = props
  const classes = useStyles()

  // Note useFormContext here instead of useForm reuses the
  // existing form context from the parent.
  const { reset, handleSubmit } = useFormContext()

  const closeForm = (): void => {
    props.onOpenStateChange(false)
    reset(defaultValues)
  }

  const onClose = (): void => {
    if (props.onCancel !== undefined) props.onCancel()
    closeForm()
  }

  const onSave: SubmitHandler<A> = (formData): void => {
    props.onSave(formData)
    closeForm()
  }

  const openAddForm = () => {
    props.onOpenStateChange(true)
  }

  return (
    <>
      {(() => {
        if (isOpen) {
          return (
            <FormContainer
              onDone={intentionallyFloat(handleSubmit(onSave))}
              onCancel={onClose}
            >
              {props.children}
            </FormContainer>
          )
        } else if (allowAdd) {
          return (
            <div className={classes.buttonList}>
              <Button
                type="button"
                onClick={openAddForm}
                color={prefersDarkMode ? 'default' : 'secondary'}
                variant="contained"
              >
                Add
              </Button>
            </div>
          )
        }
      })()}
    </>
  )
}
Example #25
Source File: Title.tsx    From tobira with Apache License 2.0 5 votes vote down vote up
EditTitleBlock: React.FC<EditTitleBlockProps> = ({ block: blockRef }) => {
    const { t } = useTranslation();


    const { content } = useFragment(graphql`
        fragment TitleEditModeBlockData on TitleBlock {
            content
        }
    `, blockRef);


    const form = useFormContext<TitleFormData>();


    const [save] = useMutation<TitleEditSaveMutation>(graphql`
        mutation TitleEditSaveMutation($id: ID!, $set: UpdateTitleBlock!) {
            updateTitleBlock(id: $id, set: $set) {
                ... BlocksBlockData
            }
        }
    `);

    const [create] = useMutation<TitleEditCreateMutation>(graphql`
        mutation TitleEditCreateMutation($realm: ID!, $index: Int!, $block: NewTitleBlock!) {
            addTitleBlock(realm: $realm, index: $index, block: $block) {
                ... ContentManageRealmData
            }
        }
    `);


    return <EditModeForm create={create} save={save}>
        <h3><Input
            placeholder={t("manage.realm.content.title.content")}
            defaultValue={content}
            css={{ display: "block" }}
            {...form.register("content")}
        /></h3>
    </EditModeForm>;
}
Example #26
Source File: FormTextField.tsx    From rn-credit-card with MIT License 5 votes vote down vote up
FormTextField = React.forwardRef<TextInput, Props>((props, ref) => {
  const {
    name,
    rules,
    validationLength = 1,
    formatter,
    onBlur,
    onValid,
    ...restOfProps
  } = props
  const { control, formState, trigger, watch } = useFormContext()
  const value = watch(name)

  useEffect(() => {
    async function validate() {
      const isValid = await trigger(name)
      if (isValid) onValid?.()
    }

    if (value?.length >= validationLength) {
      validate()
    }
  }, [value, name, validationLength, trigger]) // eslint-disable-line react-hooks/exhaustive-deps

  return (
    <Controller
      control={control}
      render={({ field }) => (
        <TextField
          // passing everything down to TextField
          // to be able to support all TextInput props
          {...restOfProps}
          ref={ref}
          testID={`TextField.${name}`}
          errorText={formState.errors[name]?.message}
          onBlur={(event) => {
            field.onBlur()
            onBlur?.(event)
          }}
          onChangeText={(text) => {
            const formatted = formatter ? formatter(field.value, text) : text
            field.onChange(formatted)
          }}
          value={field.value}
        />
      )}
      name={name}
      rules={rules}
    />
  )
})
Example #27
Source File: NumberField.tsx    From react-hook-form-generator with MIT License 5 votes vote down vote up
NumberField: FC<FieldProps<NumberFieldSchema>> = ({
  id,
  name,
  field,
  defaultValue,
}) => {
  const {
    label,
    placeholder,
    helperText,
    isRequired,
    shouldDisplay,
    styles = {},
  } = field;

  const fieldStyles = useStyles<FieldStyles>('numberField', styles);

  const { control, watch } = useFormContext();

  const values = watch(name);

  const errorMessage = useErrorMessage(name, label);

  const isVisible = useMemo(() => {
    return shouldDisplay ? shouldDisplay(values) : true;
  }, [values, shouldDisplay]);

  return isVisible ? (
    <FormControl
      key={`${name}-control`}
      isRequired={isRequired}
      isInvalid={!!errorMessage}
      {...fieldStyles.control}
    >
      {!!label && (
        <FormLabel htmlFor={name} {...fieldStyles.errorMessage}>
          {label}
        </FormLabel>
      )}
      <Controller
        name={name}
        control={control}
        defaultValue={defaultValue || 0}
        as={
          <NumberInput>
            <NumberInputField
              id={id}
              data-testid={id}
              placeholder={placeholder}
              {...fieldStyles.input}
            />
            <NumberInputStepper>
              <NumberIncrementStepper />
              <NumberDecrementStepper />
            </NumberInputStepper>
          </NumberInput>
        }
      />
      {!!helperText && (
        <FormHelperText {...fieldStyles.helperText}>
          {helperText}
        </FormHelperText>
      )}
      <FormErrorMessage {...fieldStyles.errorMessage}>
        {errorMessage}
      </FormErrorMessage>
    </FormControl>
  ) : null;
}
Example #28
Source File: MultiStepFormBody.tsx    From frontend with GNU General Public License v3.0 5 votes vote down vote up
MultiStepFormBody = ({
  children,
  onNext,
  onBack,
  onSubmit,
  onCancel,
  title,
}: IMultiStepForm): JSX.Element => {
  const { trigger, watch, errors, clearErrors } = useFormContext();
  const { currentStep, goForward, goBack, goTo } = useFormProgress();

  const lastStep = React.Children.count(children) - 1;
  const steps = React.Children.toArray(children);
  const amountOfSteps = Array.from(Array(steps.length).keys());

  const formData = watch();

  const [form, setForm] = useState({});

  const handleSubmit = (data: IFormData): void => {
    if (_.isEmpty(errors)) {
      onSubmit(data);
    }
  };

  const updateCurrentForm = () => setForm((state) => ({ ...state, ...formData }));

  const handleNext = async () => {
    const status = await trigger();

    if (!status) return;

    updateCurrentForm();

    if (currentStep === lastStep) {
      handleSubmit({ ...form, ...formData });
      return;
    }

    goForward();
    clearErrors();
    onNext(formData);
  };

  const handleBack = () => {
    updateCurrentForm();

    goBack();
    onBack(formData);
  };

  return (
    <>
      {title && <StyledTitle>{title}</StyledTitle>}
      <ProgressBar
        activeStep={currentStep}
        steps={amountOfSteps}
        changeStep={goTo}
        formData={formData}
      />
      <StyledForm>{steps[currentStep]}</StyledForm>
      <ActionButtons
        lastStep={lastStep}
        activeStep={currentStep}
        onBack={handleBack}
        onNext={handleNext}
        onCancel={onCancel}
      />
    </>
  );
}
Example #29
Source File: SwitchField.tsx    From react-hook-form-generator with MIT License 5 votes vote down vote up
SwitchField: FC<FieldProps<SwitchFieldSchema>> = ({
  id,
  name,
  field,
}) => {
  const { label, helperText, isRequired, shouldDisplay, styles = {} } = field;

  const { register, watch } = useFormContext();

  const values = watch(name);

  const fieldStyles = useStyles<SwitchFieldStyles>('switchField', styles);

  const errorMessage = useErrorMessage(name, label);

  const isVisible = useMemo(() => {
    return shouldDisplay ? shouldDisplay(values) : true;
  }, [values, shouldDisplay]);

  return isVisible ? (
    <FormControl
      key={`${name}-control`}
      isRequired={isRequired}
      isInvalid={!!errorMessage}
      {...fieldStyles.control}
    >
      {!!label && (
        <FormLabel htmlFor={name} {...fieldStyles.label}>
          {label}
        </FormLabel>
      )}
      <Switch
        name={name}
        data-testid={id}
        ref={register}
        {...fieldStyles.switch}
      />
      {!!helperText && (
        <FormHelperText {...fieldStyles.helperText}>
          {helperText}
        </FormHelperText>
      )}
      <FormErrorMessage {...fieldStyles.errorMessage}>
        {errorMessage}
      </FormErrorMessage>
    </FormControl>
  ) : null;
}