Skip to Content
Prism UI
Forms

Advanced Usage

What v1.0.0 supports beyond the basics, including two documented architectural limits and their real workarounds.

These two limitations were found while building a real, multi-page consuming application, and reproduced directly against the type system, not assumed. Both have a real, supported workaround, neither is a bug to be worked around temporarily, they're deliberate design decisions.

Nested field paths aren't supported in defineForm's configuration

createFormBuilder(registry).defineForm<TValues>({...})'s configuration object accepts one entry per top-level key of TValues. If TValues has a nested shape ({ address: { street: string } }), there is currently no way to configure address.street individually, writing 'address.street': { type: 'text', ... } does not compile.

Supported workaround: flatten the value shape instead.

interface FormValues {
  addressStreet: string; // not address.street
  addressCity: string;
}

A future, backward-compatible defineForm enhancement for nested paths may be considered, it is not implemented in v1.0.0, don't assume it works until this page is updated to describe it as supported.

Dynamic field configuration

A field's extra props (a SelectField's options, for example) are fixed once in defineForm's configuration object. There is no way to pass different props to <PrismField> on a given render based on another field's current value, this is intentional, not an oversight: static configuration, kept separate from runtime form state, is a deliberate design choice, see Configuration-Driven Design.

Supported pattern: render the field component directly through React Hook Form's own real Controller, reachable via form.control since usePrismForm returns the complete, unmodified UseFormReturn, bypassing PrismField for that one field:

import { Controller } from 'react-hook-form';
import { SelectField } from './components/prism/fields/select-field';

<Controller
  name="designation"
  control={form.control}
  render={({ field, fieldState }) => (
    <SelectField
      field={{
        name: field.name,
        value: field.value,
        onChange: field.onChange,
        onBlur: field.onBlur,
        error: fieldState.error?.message,
      }}
      label="Designation"
      options={computeOptionsFromSomeOtherFieldsValue()}
    />
  )}
/>;

This is not a workaround to be replaced by a future Prism API, it is the architecture's own "preserve full RHF access" promise working as intended, see React Hook Form Integration.

Watching, setting, and resetting values

Every React Hook Form method is reachable straight off the object usePrismForm returns, there is nothing Prism-specific to learn here:

const watchedName = form.watch('name');
form.setValue('name', 'Programmatic value');
form.reset(); // restores defaultValues
form.formState.isDirty; // reflects real edits

Accessing the raw registry and field configuration

usePrismForm also returns registry and fieldsConfig, the exact values passed to createFormBuilder and defineForm, useful for building generic tooling (a form renderer that iterates every configured field, for example) on top of a FormDefinition without re-declaring it:

for (const name of Object.keys(form.fieldsConfig)) {
  // render a <PrismField> for each configured field generically
}

On this page