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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions