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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
ConnectForm = ({ children }) => {
const methods = useFormContext()
return children({ ...methods })
}
Example #18
Source File: Content.tsx From calories-in with MIT License | 5 votes |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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;
}