Skip to main content

GenericForm

A field-config–driven form renderer powered by Formik. You create the formik instance externally (via useFormik or the library's helpers), then pass it along with a fields array — GenericFrom renders every field, handles validation display, and wires up the Formik context automatically.

📖 Storybook

Preview

Import

import { GenericFrom } from "@xocialive/ui-components";
import type { FormFieldProps } from "@xocialive/ui-components/components";

// Helper hooks / utilities
import {
buildValidationSchema,
buildInitialValues,
buildPayload,
useFormikWithValidation,
useFormikWithPayload,
} from "@xocialive/ui-components/components";
note

The export name is GenericFrom (intentional spelling in the library).

Basic usage

src/modules/items/forms/ItemForm.tsx
import React from "react";
import { useFormik } from "formik";
import * as Yup from "yup";
import { GenericFrom, FormHeader, FormActions } from "@xocialive/ui-components";
import type { FormFieldProps } from "@xocialive/ui-components/components";
import { useNavigate } from "react-router-dom";

interface ItemFormValues {
englishName: string;
arabicName: string;
code: string;
}

const fields: FormFieldProps[] = [
{
type: "text",
name: "englishName",
label: t("items.englishName"),
gridSize: { xs: 12, md: 6 },
maxLength: 100,
},
{
type: "text",
name: "arabicName",
label: t("items.arabicName"),
gridSize: { xs: 12, md: 6 },
maxLength: 100,
},
{
type: "text",
name: "code",
label: t("items.code"),
gridSize: { xs: 12, md: 6 },
maxLength: 50,
},
];

const ItemForm: React.FC = () => {
const navigate = useNavigate();

const formik = useFormik<ItemFormValues>({
initialValues: { englishName: "", arabicName: "", code: "" },
validationSchema: Yup.object({
englishName: Yup.string().required(t("validation.required")),
arabicName: Yup.string().required(t("validation.required")),
code: Yup.string().required(t("validation.required")),
}),
onSubmit: async (values) => {
await createItem(values);
navigate("/items");
},
});

return (
<>
<FormHeader
isDirty={formik.dirty}
isSubmitting={formik.isSubmitting}
onBack={() => navigate("/items")}
textOverrides={{
title: t("items.newItem"),
backButton: t("common.back"),
unsavedChanges: t("common.unsavedChanges"),
}}
/>
<GenericFrom
formik={formik}
fields={fields}
section={{
title: t("items.basicInfo"),
description: t("items.basicInfoDescription"),
}}
/>
<FormActions
isEditing={false}
isSubmitting={formik.isSubmitting}
textOverrides={{
submit: t("common.save"),
cancel: t("common.cancel"),
}}
/>
</>
);
};

export default ItemForm;

Props

PropTypeDescription
formikFormikProps<any>Required. Formik instance created externally
fieldsFormFieldProps[]Required. Field definitions
sectionSectionPropsOptional section header (title + description)
hideSectionbooleanHides the section header when true
crossFieldValidationsCrossFieldValidation[]Cross-field validation rules

FormFieldProps

interface FormFieldProps {
type:
| "text"
| "textarea"
| "select"
| "async-autocomplete"
| "async-autocomplete-v2"
| "autocomplete"
| "checkbox"
| "switch"
| "tel"
| "date";
name: string;
label: string;
gridSize?: { xs?: number; sm?: number; md?: number; lg?: number };
maxLength?: number;
textFieldType?: string; // e.g. "number", "email", "password"
options?: { label: string; value: any }[]; // for select / autocomplete
disabled?: boolean;
required?: boolean;
placeholder?: string;
}

Supported field types

typeRendered component
textTextField
textareaTextField (multiline)
selectSelect
autocompleteAutocomplete
async-autocompleteAsyncAutoComplete
async-autocomplete-v2AsyncAutoComplete (v2)
checkboxCheckbox
switchSwitch
telMuiTelInput
dateMUI DatePicker

Helper utilities

// Build a Yup schema from fields array
const schema = buildValidationSchema(fields);

// Build Formik initialValues from fields array
const initialValues = buildInitialValues(fields);

// Extract only the fields present in the fields array from formik values
const payload = buildPayload(formik.values, fields);

// Combined hook: formik + schema derived from fields
const formik = useFormikWithValidation({ fields, onSubmit, initialValues });

// Combined hook: formik + payload builder
const { formik, payload } = useFormikWithPayload({ fields, onSubmit, initialValues });

See also