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 editsAccessing 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
}