CandidFormVisitor
CandidFormVisitor generates form metadata from Candid IDL types.
Use it when you already have an IDL.ServiceClass and want low-level metadata for dynamic forms.
If you want a higher-level API, use MetadataReactor which uses this visitor internally.
Import
Section titled “Import”import { CandidFormVisitor } from "@ic-reactor/candid"Quick Example
Section titled “Quick Example”import { CandidFormVisitor } from "@ic-reactor/candid"import { IDL } from "@icp-sdk/core/candid"
const visitor = new CandidFormVisitor()const service = idlFactory({ IDL })
const serviceMeta = visitor.visitService(service)const methodMeta = serviceMeta["icrc1_transfer"]
console.log(methodMeta?.schema) // Zod tuple schema for all argsconsole.log(methodMeta?.defaults) // default form valuesMethod Metadata
Section titled “Method Metadata”type FormArgumentsMeta = { candidType: string functionType: "query" | "update" | "value" functionName: string args: FormFieldNode[] defaults: unknown[] schema: z.ZodTypeAny argCount: number isEmpty: boolean}Field Metadata
Section titled “Field Metadata”Every FormFieldNode includes:
| Property | Type | Description |
|---|---|---|
type |
FormFieldType |
Candid field category |
label |
string |
Raw field label |
displayLabel |
string |
Human-readable label |
name |
string |
Form path |
schema |
z.ZodTypeAny |
Field-level validation schema |
component |
FormFieldComponentType |
Suggested renderer component |
renderHint |
FormRenderHint |
Primitive/compound and input type hints |
defaultValue |
unknown |
Default value for initialization |
candidType |
string |
Original Candid type text |
UI Hints
Section titled “UI Hints”Typical component values:
record-containertuple-containervariant-selectoptional-togglevector-listblob-uploadprincipal-inputtext-inputnumber-inputboolean-checkboxnull-hiddenrecursive-lazyunknown-fallback
renderHint shape:
type FormRenderHint = { isCompound: boolean isPrimitive: boolean inputType?: "text" | "number" | "checkbox" | "select" | "file" | "textarea"}Validation Example (TanStack Form)
Section titled “Validation Example (TanStack Form)”The form metadata holds display types: text for principals and numbers, null
for an empty opt, { _type } for a variant. An actor takes Candid values, so
the submitted values are converted to Candid before the call.
import { didToDisplayCodec } from "@ic-reactor/core"import { IDL } from "@icp-sdk/core/candid"import { useForm } from "@tanstack/react-form"
const { argTypes } = service.fieldsAsObject()["icrc1_transfer"]const argsCodec = didToDisplayCodec(IDL.Tuple(...argTypes))
// The schema validates `unknown`, so the form's values are typed `unknown` tooconst defaultValues: unknown = methodMeta.defaults
// A hook: call it from a componentfunction useTransferForm() { return useForm({ defaultValues, validators: { onBlur: methodMeta.schema }, onSubmit: async ({ value }) => { // Principal, bigint, [] or [x] for an opt, { Tag: payload } for a variant. // An untyped codec returns `unknown`, so name the tuple the actor takes. const args = argsCodec.asCandid(value) as Parameters< typeof actor.icrc1_transfer > await actor.icrc1_transfer(...args) }, })}When to Use MetadataReactor Instead
Section titled “When to Use MetadataReactor Instead”Use MetadataReactor if you want to work directly from canister ID + client manager and avoid manual visitor wiring.