Skip to content

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 { CandidFormVisitor } from "@ic-reactor/candid"
import { CandidFormVisitor } from "@ic-reactor/candid"
import { IDL } from "@icp-sdk/core/candid"
const visitor = new CandidFormVisitor()
const service = idlFactory({ IDL })
const serviceMeta = service.accept(visitor, null)
const methodMeta = serviceMeta["icrc1_transfer"]
console.log(methodMeta?.schema) // Zod tuple schema for all args
console.log(methodMeta?.defaults) // default form values
type FormArgumentsMeta = {
candidType: string
functionType: "query" | "update" | "value"
functionName: string
args: FormFieldNode[]
defaults: unknown[]
schema: z.ZodTypeAny
argCount: number
isEmpty: boolean
}

Every FormFieldNode includes:

PropertyTypeDescription
typeFormFieldTypeCandid field category
labelstringRaw field label
displayLabelstringHuman-readable label
namestringForm path
schemaz.ZodTypeAnyField-level validation schema
componentFormFieldComponentTypeSuggested renderer component
renderHintFormRenderHintPrimitive/compound and input type hints
defaultValueunknownDefault value for initialization
candidTypestringOriginal Candid type text

Typical component values:

  • record-container
  • tuple-container
  • variant-select
  • optional-toggle
  • vector-list
  • blob-upload
  • principal-input
  • text-input
  • number-input
  • boolean-checkbox
  • null-hidden
  • recursive-lazy
  • unknown-fallback

renderHint shape:

type FormRenderHint = {
isCompound: boolean
isPrimitive: boolean
inputType?: "text" | "number" | "checkbox" | "select" | "file" | "textarea"
}
const form = useForm({
defaultValues: methodMeta.defaults,
validators: { onBlur: methodMeta.schema },
onSubmit: async ({ value }) => {
await actor.icrc1_transfer(...value)
},
})

Use MetadataReactor if you want to work directly from canister ID + client manager and avoid manual visitor wiring.