Skip to content

Add optional schema-driven form renderer with component registry #152

Description

@piyushzala158

Idea

It would be useful to have an optional schema-driven rendering layer on top of Formisch's existing headless primitives.

In one of my current projects we use React Hook Form in a schema-based way. Instead of writing useForm, Controller, validation, submit handling, and input wiring repeatedly in every form, we have a common form context wrapper and a set of predefined input components. The backend sends a form schema/descriptor with field kinds like input, number, boolean, radio, etc. The frontend maps those field kinds to registered components and renders the form automatically.

That gives us a few benefits:

  • no duplicate form setup code across many forms
  • consistent UI and behavior across all forms
  • backend-controlled form shape
  • shared validation rules between backend and frontend
  • one common place for submit handling, validation triggering, layout, error rendering, etc.

Proposal

Could Formisch support a similar optional pattern, maybe as a helper package or higher-level API, where users can define a Valibot schema plus UI metadata and register their own field components for different input kinds?

Rough API sketch:

const form = useForm({ schema: UserSchema });

const components = {
  text: TextInputField,
  number: NumberInputField,
  boolean: CheckboxField,
  radio: RadioGroupField,
  select: SelectField,
};

<SchemaForm
  of={form}
  fields={fieldsFromBackend}
  components={components}
  onSubmit={handleSubmit}
/>

Where each registered component would receive the Formisch field store/props/errors/input for its path, so the user still controls the UI while Formisch handles the repeated wiring.

The backend descriptor could look something like:

[
  { name: 'firstName', type: 'text', label: 'First name', required: true },
  { name: 'age', type: 'number', label: 'Age' },
  { name: 'newsletter', type: 'boolean', label: 'Subscribe?' },
  {
    name: 'role',
    type: 'radio',
    label: 'Role',
    options: [
      { label: 'Admin', value: 'admin' },
      { label: 'User', value: 'user' },
    ],
  },
]

Why this might fit Formisch

Formisch is already schema-first and headless, so this could stay optional while giving teams a productive way to build dynamic/backend-controlled forms without reimplementing the same renderer around Formisch in every app.

It could also make Formisch more attractive for admin panels, internal tools, CMS-like workflows, onboarding flows, and other products where many forms are generated from a shared schema/descriptor.

Questions

Related/adjacent issues I found while searching: #34 and #67.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions