Advanced

API reference

Complete reference for all exports from @nestledjs/forms, @nestledjs/forms-native, and @nestledjs/forms-core.


Components

Form (web)

import { Form } from '@nestledjs/forms'
PropTypeRequiredDescription
idstringYesUnique form identifier
fieldsFormField[]NoDeclarative field definitions
submit(values: T) => voidYesSubmit handler
initialValuesPartial<T>NoPre-fill form values
readOnlybooleanNoMake all fields read-only
themeFormThemeNoCustom theme object
validateOnBlurbooleanNoValidate on field blur
validateOnChangebooleanNoValidate on field change
childrenReactNodeNoSubmit buttons, imperative fields, etc.

NativeForm (React Native)

import { NativeForm } from '@nestledjs/forms-native'

Same props as Form but rendered with React Native components.

RenderFormField

import { RenderFormField } from '@nestledjs/forms'
PropTypeRequiredDescription
fieldFormFieldYesField definition from FormFieldClass

ApolloSearchProvider

import { ApolloSearchProvider } from '@nestledjs/forms/apollo'
// or '@nestledjs/forms-native/apollo' / '@nestledjs/forms-core/apollo'

Enables searchSelectApollo and searchSelectMultiApollo fields. Place inside your existing <ApolloProvider>. Works with @apollo/client v3 and v4. The /apollo subpath is the only entry point that imports @apollo/client.

PropTypeRequiredDescription
childrenReactNodeYesYour app or form tree

SearchQueryProvider

import { SearchQueryProvider } from '@nestledjs/forms-core'

Backs Apollo search select fields with a custom data layer (urql, TanStack Query, fetch) instead of Apollo Client.

PropTypeRequiredDescription
useSearchQueryUseSearchQueryYesHook that executes the field's document
childrenReactNodeYesYour app or form tree

PhoneField

import { PhoneField } from '@nestledjs/forms/phone'

Direct import of the phone field component. It lives on its own subpath (no longer exported from @nestledjs/forms) to keep libphonenumber's ~150 KB metadata out of the main bundle; declarative usage via FormFieldClass.phone() lazy-loads it automatically.


FormFieldClass factory methods

import { FormFieldClass } from '@nestledjs/forms'

All methods follow the signature: FormFieldClass.method(key: string, options?: Options)

Text input fields

MethodDescription
FormFieldClass.text(key, options?)Single-line text input
FormFieldClass.textArea(key, options?)Multi-line text input
FormFieldClass.email(key, options?)Email input with validation
FormFieldClass.password(key, options?)Masked password input
FormFieldClass.url(key, options?)URL input with validation
FormFieldClass.phone(key, options?)Phone number with country code

Numeric fields

MethodDescription
FormFieldClass.number(key, options?)Numeric input with min/max/step
FormFieldClass.currency(key, options?)Currency input with formatting

Selection fields

MethodDescription
FormFieldClass.select(key, options?)Single-select dropdown
FormFieldClass.multiSelect(key, options?)Multi-select dropdown
FormFieldClass.enumSelect(key, options?)Select from TypeScript enum
FormFieldClass.radio(key, options?)Radio button group
FormFieldClass.checkboxGroup(key, options?)Checkbox group

Search select fields

MethodDescription
FormFieldClass.searchSelect(key, options?)Searchable single-select
FormFieldClass.searchSelectApollo(key, options?)Apollo GraphQL single-select
FormFieldClass.searchSelectMulti(key, options?)Searchable multi-select
FormFieldClass.searchSelectMultiApollo(key, options?)Apollo GraphQL multi-select

Boolean fields

MethodDescription
FormFieldClass.checkbox(key, options?)Standard checkbox
FormFieldClass.switch(key, options?)Toggle switch
FormFieldClass.customCheckbox(key, options?)Custom-styled checkbox

Date & time fields

MethodDescription
FormFieldClass.datePicker(key, options?)Date picker
FormFieldClass.dateTimePicker(key, options?)Date and time picker
FormFieldClass.timePicker(key, options?)Time picker

Utility fields

MethodDescription
FormFieldClass.markdownEditor(key, options?)Rich text markdown editor
FormFieldClass.content(key, options?)Display-only content
FormFieldClass.custom(key, options?)Custom component field
FormFieldClass.button(key, options?)Action button

Shared field options

All field types accept these options:

interface BaseFieldOptions {
  // Display
  label?: string
  placeholder?: string
  helpText?: string
  hidden?: boolean

  // State
  required?: boolean
  disabled?: boolean
  readOnly?: boolean
  readOnlyStyle?: 'value' | 'disabled'
  defaultValue?: any

  // Conditional logic
  showWhen?: (formValues: Record<string, any>) => boolean
  requiredWhen?: (formValues: Record<string, any>) => boolean
  disabledWhen?: (formValues: Record<string, any>) => boolean
  validateWhen?: (formValues: Record<string, any>) => boolean

  // Validation
  validate?: (value: any) => true | string | Promise<true | string>
  schema?: ZodTypeAny
  validateWithForm?: (
    value: any,
    formValues: Record<string, any>,
  ) => true | string
  validationDependencies?: string[]
  validationGroup?: string
  errorMessages?: { required?: string; [key: string]: string | undefined }

  // Layout
  wrapperClassName?: string
  layout?: 'horizontal' | 'vertical'
  customWrapper?: (children: React.ReactNode) => React.ReactElement

  // Transform
  submitTransform?: (value: any) => unknown
}

Hooks

useFormContext

import { useFormContext } from '@nestledjs/forms'

const {
  formValues, // Record<string, any> — current form values
  errors, // Record<string, string> — validation errors
  isSubmitting, // boolean — whether form is submitting
  setValue, // (key: string, value: any) => void
  setError, // (key: string, error: string) => void
  reset, // () => void — reset to initial values
  validateGroup, // (group: string) => Promise<boolean>
} = useFormContext()

useFormValue

Reactively read a single field's value from any component inside <Form>.

import { useFormValue } from '@nestledjs/forms'

function Mirror() {
  const answer = useFormValue<string>('answer')
  return <p>You picked: {answer}</p>
}

Don't use form.watch() to read during render

form.watch(name) compiles, returns the right value on first render, and then silently never updates — no error, no warning, no type error. It re-renders only the component that owns useForm(), which is <Form> itself; <Form> passes children straight through, so React reuses that element reference and skips reconciling the subtree. Use useFormValue instead. The callback form, form.watch(cb), is fine.

useFormValues

The whole-form counterpart. Re-renders on any change, so prefer useFormValue when you only need one field.

import { useFormValues } from '@nestledjs/forms'

const values = useFormValues()

useWatch

react-hook-form's primitive, re-exported so you subscribe through the same instance <Form> uses. react-hook-form is a peer dependency — under pnpm's isolated node_modules an app that doesn't depend on it directly cannot resolve it, and adding it risks a second copy with a mismatched version.

import { useWatch, useFormContext } from '@nestledjs/forms'

const form = useFormContext()
const answer = useWatch({ control: form.control, name: 'answer' })

useFormConfig

import { useFormConfig } from '@nestledjs/forms'

const {
  readOnly, // boolean
  validateOnBlur, // boolean
  validateOnChange, // boolean
} = useFormConfig()

useFormTheme

import { useFormTheme } from '@nestledjs/forms'

const theme = useFormTheme()
// theme.input, theme.label, theme.error, etc.

useNativeFormSubmit

import { useNativeFormSubmit } from '@nestledjs/forms-native'

const submitForm = useNativeFormSubmit()
// (() => Promise<void>) | null — null outside a NativeForm

<Pressable onPress={() => submitForm?.()} />

Returns NativeForm's submit trigger for custom submit buttons: runs validation, applies each field's submitTransform, then calls the form's submit prop.

useApolloSearchQuery

import { useApolloSearchQuery } from '@nestledjs/forms/apollo'

The Apollo implementation of UseSearchQuery used by ApolloSearchProvider. Useful as a reference when writing a custom adapter.


Theme utilities

tailwindTheme

import { tailwindTheme } from '@nestledjs/forms'

The default Tailwind CSS theme. Applied automatically unless you provide a custom theme.

createCustomTheme

import { createCustomTheme } from '@nestledjs/forms'

const theme = createCustomTheme({
  input: 'custom-input-classes',
  label: 'custom-label-classes',
})
// Merges with tailwindTheme — only override what you need

createFinalTheme

import { createFinalTheme } from '@nestledjs/forms'

const theme = createFinalTheme(baseTheme, overrides)
// Merges overrides into baseTheme at runtime

themeReference

import { themeReference } from '@nestledjs/forms'
// Object listing all theme property names and descriptions

generateThemeTemplate

import { generateThemeTemplate } from '@nestledjs/forms'
// Returns a theme object with all properties set to empty strings

Types

FormField

import type { FormField } from '@nestledjs/forms'
// Union type of all possible field definitions

FormFieldType

import { FormFieldType } from '@nestledjs/forms'
// Enum of all field type identifiers

FormTheme

import type { FormTheme } from '@nestledjs/forms'
// Interface for the complete theme object

FormProps

import type { FormProps } from '@nestledjs/forms'
// Props interface for the Form component

UseSearchQuery

import type { UseSearchQuery } from '@nestledjs/forms-core'

type UseSearchQuery = <TData = any>(
  document: DocumentNode | TypedDocumentNode<TData>,
  options?: { variables?: Record<string, unknown> },
) => {
  data: TData | undefined
  loading: boolean
  refetch: (variables?: Record<string, unknown>) => Promise<{ data?: TData }>
}

The hook contract for custom search query adapters passed to SearchQueryProvider. The returned data must be referentially stable between renders unless the result changed.


Validation utilities

import {
  createFieldValidation, // Create a validation function for a field
  createFormResolver, // Create a form-level resolver
  validateGroup, // Validate a specific validation group
} from '@nestledjs/forms'

Submit transform utilities

import {
  singleSelectSubmitTransform, // Option object → ID string
  multiSelectSubmitTransform, // Option objects → ID string array
  resolveSubmitTransform, // Field's explicit transform, or its per-type default
} from '@nestledjs/forms-core'

Applied automatically at submit time for searchSelectApollo, searchSelectMultiApollo, multiSelect, and searchSelectMulti fields. An explicit submitTransform on the field always wins. Still re-exported from their previous locations.


Currency utilities

import {
  currencies, // Array of all supported currency configurations
  formatCurrency, // Format a number as currency string
  getCurrencySymbol, // Get the symbol for a currency code
} from '@nestledjs/forms'

Date/time utilities

import {
  formatDate, // Format a date value
  formatDateTime, // Format a datetime value
  formatTime, // Format a time value
} from '@nestledjs/forms'

Timezone-safe helpers for converting between Date objects and local date strings (used internally by the date pickers to avoid cross-timezone date corruption):

import {
  parseLocalDate, // 'YYYY-MM-DD' string → Date in local time
  formatLocalDate, // Date → 'YYYY-MM-DD' string in local time
  parseLocalDateTime, // 'YYYY-MM-DDTHH:mm' string → Date in local time
  formatLocalDateTime, // Date → 'YYYY-MM-DDTHH:mm' string in local time
} from '@nestledjs/forms-core'
Previous
Apollo integration