or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced.mdfield-api.mdform-api.mdframework-integrations.mdhooks.mdindex.mdvalidation.md

form-api.mddocs/

0

# Form Management

1

2

The FormApi class provides comprehensive form state management including validation, submission handling, field coordination, and lifecycle events. It serves as the core of TanStack React Form's state management system.

3

4

## Capabilities

5

6

### FormApi Class

7

8

Core form management class with methods for validation, submission, and field manipulation.

9

10

```typescript { .api }

11

class FormApi<

12

TFormData,

13

TOnMount extends undefined | FormValidateOrFn<TFormData> = undefined,

14

TOnChange extends undefined | FormValidateOrFn<TFormData> = undefined,

15

TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData> = undefined,

16

TOnBlur extends undefined | FormValidateOrFn<TFormData> = undefined,

17

TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData> = undefined,

18

TOnSubmit extends undefined | FormValidateOrFn<TFormData> = undefined,

19

TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData> = undefined,

20

TOnDynamic extends undefined | FormValidateOrFn<TFormData> = undefined,

21

TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData> = undefined,

22

TOnServer extends undefined | FormAsyncValidateOrFn<TFormData> = undefined,

23

TSubmitMeta = never,

24

> {

25

/** Store instance for reactive state management */

26

store: Store<FormState<TFormData, ...>>;

27

28

/** Current form state */

29

state: FormState<TFormData, ...>;

30

31

/** Form configuration options */

32

options: FormOptions<TFormData, ...>;

33

34

/** Record of field information for each field in the form */

35

fieldInfo: Record<DeepKeys<TFormData>, FieldInfo<TFormData>>;

36

37

constructor(opts?: FormOptions<TFormData, ...>);

38

39

/**

40

* Mounts the form and runs mount validation

41

* Call this when the form component mounts to initialize validation and event listeners

42

* @returns Cleanup function to unmount the form and remove listeners

43

*/

44

mount(): () => void;

45

46

/**

47

* Updates form options with new configuration

48

* Updates values and state if defaultValues or defaultState changed and form is pristine

49

* Re-evaluates transform function if transform deps changed

50

* @param options - Form options to update

51

*/

52

update(

53

options?: FormOptions<TFormData, ...>,

54

): void;

55

56

/**

57

* Resets the form to its initial state

58

* @param values - Optional new values to reset to (defaults to defaultValues)

59

* @param opts - Options for reset behavior

60

*/

61

reset(values?: TFormData, opts?: { keepDefaultValues?: boolean }): void;

62

63

/**

64

* Validates all fields in the form

65

* @param cause - Reason for validation (e.g., 'change', 'blur', 'submit')

66

* @returns Promise that resolves to array of validation errors

67

*/

68

validateAllFields(

69

cause: ValidationCause,

70

): Promise<ValidationError[]>;

71

72

/**

73

* Validates array field children starting from a specific index

74

* @param field - Field path to validate

75

* @param index - Starting index for validation

76

* @param cause - Reason for validation

77

* @returns Promise that resolves to array of validation errors

78

*/

79

validateArrayFieldsStartingFrom<TField extends DeepKeys<TFormData>>(

80

field: TField,

81

index: number,

82

cause: ValidationCause,

83

): Promise<ValidationError[]>;

84

85

/**

86

* Validates a specific field

87

* @param field - Field path to validate

88

* @param cause - Reason for validation

89

* @returns Promise that resolves to array of validation errors

90

*/

91

validateField<TField extends DeepKeys<TFormData>>(

92

field: TField,

93

cause: ValidationCause,

94

): Promise<ValidationError[]>;

95

96

/**

97

* Handles form submission with optional metadata

98

* @param submitMeta - Optional metadata to pass to submit handlers

99

* @returns Promise that resolves when submission completes

100

*/

101

handleSubmit(submitMeta?: TSubmitMeta): Promise<void>;

102

103

/**

104

* Gets the current value of a field

105

* @param field - Field path

106

* @returns Current field value

107

*/

108

getFieldValue<TField extends DeepKeys<TFormData>>(

109

field: TField,

110

): DeepValue<TFormData, TField>;

111

112

/**

113

* Gets the metadata for a field

114

* @param field - Field path

115

* @returns Field metadata

116

*/

117

getFieldMeta<TField extends DeepKeys<TFormData>>(

118

field: TField,

119

): FieldMeta<DeepValue<TFormData, TField>, any, any, ...> | undefined;

120

121

/**

122

* Sets the metadata for a field

123

* @param field - Field path

124

* @param updater - Function or value to update metadata

125

*/

126

setFieldMeta<TField extends DeepKeys<TFormData>>(

127

field: TField,

128

updater: Updater<FieldMeta<DeepValue<TFormData, TField>, any, any, ...>>,

129

): void;

130

131

/**

132

* Sets the value of a field

133

* @param field - Field path

134

* @param updater - Function or value to set

135

* @param opts - Options to control metadata updates and validation

136

*/

137

setFieldValue<TField extends DeepKeys<TFormData>>(

138

field: TField,

139

updater: Updater<DeepValue<TFormData, TField>>,

140

opts?: UpdateMetaOptions,

141

): void;

142

143

/**

144

* Deletes a field from the form

145

* @param field - Field path to delete

146

*/

147

deleteField<TField extends DeepKeys<TFormData>>(

148

field: TField,

149

): void;

150

151

/**

152

* Pushes a value to an array field

153

* @param field - Field path (must be an array)

154

* @param value - Value to push

155

* @param opts - Options to control metadata updates and validation

156

*/

157

pushFieldValue<TField extends DeepKeys<TFormData>>(

158

field: TField,

159

value: DeepValue<TFormData, TField> extends Array<infer U> ? U : never,

160

opts?: UpdateMetaOptions,

161

): void;

162

163

/**

164

* Inserts a value at a specific index in an array field

165

* @param field - Field path (must be an array)

166

* @param index - Index at which to insert

167

* @param value - Value to insert

168

* @param opts - Options to control metadata updates and validation

169

*/

170

insertFieldValue<TField extends DeepKeys<TFormData>>(

171

field: TField,

172

index: number,

173

value: DeepValue<TFormData, TField> extends Array<infer U> ? U : never,

174

opts?: UpdateMetaOptions,

175

): Promise<void>;

176

177

/**

178

* Replaces a value at a specific index in an array field

179

* @param field - Field path (must be an array)

180

* @param index - Index to replace

181

* @param value - New value

182

* @param opts - Options to control metadata updates and validation

183

*/

184

replaceFieldValue<TField extends DeepKeys<TFormData>>(

185

field: TField,

186

index: number,

187

value: DeepValue<TFormData, TField> extends Array<infer U> ? U : never,

188

opts?: UpdateMetaOptions,

189

): Promise<void>;

190

191

/**

192

* Removes a value at a specific index from an array field

193

* @param field - Field path (must be an array)

194

* @param index - Index to remove

195

* @param opts - Options to control metadata updates and validation

196

*/

197

removeFieldValue<TField extends DeepKeys<TFormData>>(

198

field: TField,

199

index: number,

200

opts?: UpdateMetaOptions,

201

): Promise<void>;

202

203

/**

204

* Swaps two values in an array field

205

* @param field - Field path (must be an array)

206

* @param index1 - First index

207

* @param index2 - Second index

208

* @param opts - Options to control metadata updates and validation

209

*/

210

swapFieldValues<TField extends DeepKeys<TFormData>>(

211

field: TField,

212

index1: number,

213

index2: number,

214

opts?: UpdateMetaOptions,

215

): void;

216

217

/**

218

* Moves a value from one index to another in an array field

219

* @param field - Field path (must be an array)

220

* @param index1 - Source index

221

* @param index2 - Destination index

222

* @param opts - Options to control metadata updates and validation

223

*/

224

moveFieldValues<TField extends DeepKeys<TFormData>>(

225

field: TField,

226

index1: number,

227

index2: number,

228

opts?: UpdateMetaOptions,

229

): void;

230

231

/**

232

* Clears all values from an array field

233

* @param field - Field path (must be an array)

234

* @param opts - Options to control metadata updates and validation

235

*/

236

clearFieldValues<TField extends DeepKeys<TFormData>>(

237

field: TField,

238

opts?: UpdateMetaOptions,

239

): void;

240

241

/**

242

* Resets a field to its default value

243

* @param field - Field path to reset

244

*/

245

resetField<TField extends DeepKeys<TFormData>>(

246

field: TField,

247

): void;

248

249

/**

250

* Gets the field info of the specified field including instance and validation metadata

251

* @param field - Field path to get info for

252

* @returns FieldInfo containing field instance and validation metadata

253

*/

254

getFieldInfo<TField extends DeepKeys<TFormData>>(

255

field: TField,

256

): FieldInfo<TFormData>;

257

258

/**

259

* Updates the form's errorMap directly

260

* Useful for setting server-side validation errors

261

* @param errorMap - New error map to set

262

*/

263

setErrorMap(

264

errorMap: FormValidationErrorMap<

265

TFormData,

266

UnwrapFormValidateOrFn<TOnMount>,

267

UnwrapFormValidateOrFn<TOnChange>,

268

UnwrapFormAsyncValidateOrFn<TOnChangeAsync>,

269

UnwrapFormValidateOrFn<TOnBlur>,

270

UnwrapFormAsyncValidateOrFn<TOnBlurAsync>,

271

UnwrapFormValidateOrFn<TOnSubmit>,

272

UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>,

273

UnwrapFormValidateOrFn<TOnDynamic>,

274

UnwrapFormAsyncValidateOrFn<TOnDynamicAsync>,

275

UnwrapFormAsyncValidateOrFn<TOnServer>

276

>,

277

): void;

278

279

/**

280

* Returns both form-level and field-level errors

281

* Provides a complete view of all validation errors in the form

282

* @returns Object containing form errors and field errors

283

*/

284

getAllErrors(): {

285

form: {

286

errors: Array<

287

| UnwrapFormValidateOrFn<TOnMount>

288

| UnwrapFormAsyncValidateOrFn<TOnChangeAsync>

289

| UnwrapFormValidateOrFn<TOnChange>

290

| UnwrapFormValidateOrFn<TOnBlur>

291

| UnwrapFormAsyncValidateOrFn<TOnBlurAsync>

292

| UnwrapFormValidateOrFn<TOnSubmit>

293

| UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>

294

| UnwrapFormValidateOrFn<TOnDynamic>

295

| UnwrapFormAsyncValidateOrFn<TOnDynamicAsync>

296

| UnwrapFormAsyncValidateOrFn<TOnServer>

297

>;

298

errorMap: ValidationErrorMap<

299

| UnwrapFormValidateOrFn<TOnMount>

300

| UnwrapFormAsyncValidateOrFn<TOnChangeAsync>

301

| UnwrapFormValidateOrFn<TOnChange>

302

| UnwrapFormValidateOrFn<TOnBlur>

303

| UnwrapFormAsyncValidateOrFn<TOnBlurAsync>

304

| UnwrapFormValidateOrFn<TOnSubmit>

305

| UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>

306

| UnwrapFormValidateOrFn<TOnDynamic>

307

| UnwrapFormAsyncValidateOrFn<TOnDynamicAsync>

308

| UnwrapFormAsyncValidateOrFn<TOnServer>

309

>;

310

};

311

fields: Record<

312

DeepKeys<TFormData>,

313

{ errors: ValidationError[]; errorMap: ValidationErrorMap }

314

>;

315

};

316

317

/**

318

* Parses form values with a Standard Schema without setting internal errors

319

* Useful for one-off validation checks without affecting form state

320

* @param schema - The Standard Schema to validate against

321

* @returns Validation error if any, undefined if valid

322

*/

323

parseValuesWithSchema(

324

schema: StandardSchemaV1<TFormData, unknown>,

325

): ValidationError | undefined;

326

327

/**

328

* Async version of parseValuesWithSchema

329

* Parses form values with a Standard Schema without setting internal errors

330

* @param schema - The Standard Schema to validate against

331

* @returns Promise resolving to validation error if any, undefined if valid

332

*/

333

parseValuesWithSchemaAsync(

334

schema: StandardSchemaV1<TFormData, unknown>,

335

): Promise<ValidationError | undefined>;

336

337

/**

338

* Gets the unique form identifier

339

* Useful for debugging and devtools integration

340

*/

341

get formId(): string;

342

}

343

```

344

345

### ReactFormExtendedApi

346

347

React-specific extension of FormApi with Field component and Subscribe function.

348

349

```typescript { .api }

350

type ReactFormExtendedApi<

351

TFormData,

352

TOnMount extends undefined | FormValidateOrFn<TFormData>,

353

TOnChange extends undefined | FormValidateOrFn<TFormData>,

354

TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,

355

TOnBlur extends undefined | FormValidateOrFn<TFormData>,

356

TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,

357

TOnSubmit extends undefined | FormValidateOrFn<TFormData>,

358

TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,

359

TOnDynamic extends undefined | FormValidateOrFn<TFormData>,

360

TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,

361

TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,

362

TSubmitMeta,

363

> = FormApi<

364

TFormData,

365

TOnMount,

366

TOnChange,

367

TOnChangeAsync,

368

TOnBlur,

369

TOnBlurAsync,

370

TOnSubmit,

371

TOnSubmitAsync,

372

TOnDynamic,

373

TOnDynamicAsync,

374

TOnServer,

375

TSubmitMeta

376

> & {

377

/**

378

* A React component to render form fields

379

* Automatically bound to this form instance

380

*/

381

Field: FieldComponent<

382

TFormData,

383

TOnMount,

384

TOnChange,

385

TOnChangeAsync,

386

TOnBlur,

387

TOnBlurAsync,

388

TOnSubmit,

389

TOnSubmitAsync,

390

TOnDynamic,

391

TOnDynamicAsync,

392

TOnServer,

393

TSubmitMeta

394

>;

395

396

/**

397

* A Subscribe function to listen and react to form state changes

398

* Useful for side effects or conditional rendering based on state

399

*/

400

Subscribe: <TSelected = FormState<TFormData, ...>>(props: {

401

selector?: (state: FormState<TFormData, ...>) => TSelected;

402

children: ((state: TSelected) => ReactNode) | ReactNode;

403

}) => ReactNode;

404

};

405

```

406

407

### FormOptions

408

409

Configuration options for creating a form instance.

410

411

```typescript { .api }

412

interface FormOptions<

413

TFormData,

414

TOnMount extends undefined | FormValidateOrFn<TFormData>,

415

TOnChange extends undefined | FormValidateOrFn<TFormData>,

416

TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,

417

TOnBlur extends undefined | FormValidateOrFn<TFormData>,

418

TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,

419

TOnSubmit extends undefined | FormValidateOrFn<TFormData>,

420

TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,

421

TOnDynamic extends undefined | FormValidateOrFn<TFormData>,

422

TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,

423

TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,

424

TSubmitMeta,

425

> extends BaseFormOptions<TFormData, TSubmitMeta> {

426

/** Form-level validators */

427

validators?: FormValidators<

428

TFormData,

429

TOnMount,

430

TOnChange,

431

TOnChangeAsync,

432

TOnBlur,

433

TOnBlurAsync,

434

TOnSubmit,

435

TOnSubmitAsync,

436

TOnDynamic,

437

TOnDynamicAsync,

438

TOnServer

439

>;

440

441

/** Form transformation configuration */

442

transform?: FormTransform<

443

TFormData,

444

TOnMount,

445

TOnChange,

446

TOnChangeAsync,

447

TOnBlur,

448

TOnBlurAsync,

449

TOnSubmit,

450

TOnSubmitAsync,

451

TOnDynamic,

452

TOnDynamicAsync,

453

TOnServer,

454

TSubmitMeta

455

>;

456

457

/** Form identifier used for devtools and debugging */

458

formId?: string;

459

460

/** If true, allows form submission even when validation fails */

461

canSubmitWhenInvalid?: boolean;

462

463

/** Debounce time in milliseconds for async validation */

464

asyncDebounceMs?: number;

465

466

/** Whether to always run async validation */

467

asyncAlways?: boolean;

468

469

/** Initial form values */

470

defaultValues?: TFormData;

471

472

/** Initial form state */

473

defaultState?: Partial<FormState<TFormData, ...>>;

474

475

/** Custom validation logic function */

476

validationLogic?: ValidationLogicFn;

477

478

/**

479

* Submit handler called when form is valid

480

* @param props - Object containing form value, API instance, and optional metadata

481

*/

482

onSubmit?: (props: {

483

value: TFormData;

484

formApi: FormApi<TFormData, ...>;

485

meta?: TSubmitMeta;

486

}) => any | Promise<any>;

487

488

/**

489

* Handler called when form submission is attempted but form is invalid

490

* @param props - Object containing form API instance

491

*/

492

onSubmitInvalid?: (props: {

493

value: TFormData;

494

formApi: FormApi<TFormData, ...>;

495

}) => void;

496

497

/** Form-level lifecycle event listeners */

498

listeners?: FormListeners<

499

TFormData,

500

TOnMount,

501

TOnChange,

502

TOnChangeAsync,

503

TOnBlur,

504

TOnBlurAsync,

505

TOnSubmit,

506

TOnSubmitAsync,

507

TOnDynamic,

508

TOnDynamicAsync,

509

TOnServer,

510

TSubmitMeta

511

>;

512

}

513

514

interface BaseFormOptions<TFormData, TSubmitMeta> {

515

/** Initial form values */

516

defaultValues?: TFormData;

517

518

/** Metadata passed from handleSubmit to onSubmit function */

519

onSubmitMeta?: TSubmitMeta;

520

}

521

```

522

523

### FormState

524

525

Complete form state interface with base and derived properties.

526

527

```typescript { .api }

528

interface FormState<

529

TFormData,

530

TOnMount extends undefined | FormValidateOrFn<TFormData>,

531

TOnChange extends undefined | FormValidateOrFn<TFormData>,

532

TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,

533

TOnBlur extends undefined | FormValidateOrFn<TFormData>,

534

TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,

535

TOnSubmit extends undefined | FormValidateOrFn<TFormData>,

536

TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,

537

TOnDynamic extends undefined | FormValidateOrFn<TFormData>,

538

TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,

539

TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,

540

> extends BaseFormState<TFormData, ...>,

541

DerivedFormState<TFormData, ...> {}

542

543

interface BaseFormState<TFormData, ...> {

544

/** Current form values */

545

values: TFormData;

546

547

/** Map of form-level validation errors by trigger type */

548

errorMap: ValidationErrorMap<...>;

549

550

/** Metadata for validation execution by trigger type */

551

validationMetaMap: Record<ValidationErrorMapKeys, ValidationMeta | undefined>;

552

553

/** Record of base field metadata for each field (not including derived properties) */

554

fieldMetaBase: Record<DeepKeys<TFormData>, AnyFieldMetaBase>;

555

556

/** Whether the form is currently submitting (after handleSubmit, before onSubmit completes) */

557

isSubmitting: boolean;

558

559

/** Whether the onSubmit function has completed successfully */

560

isSubmitted: boolean;

561

562

/** Whether the form or any fields are currently validating */

563

isValidating: boolean;

564

565

/** Number of times submission has been attempted */

566

submissionAttempts: number;

567

568

/** Whether the last submission was successful */

569

isSubmitSuccessful: boolean;

570

}

571

572

interface DerivedFormState<TFormData, ...> {

573

/** Form-level validation errors array */

574

errors: ValidationError[];

575

576

/** Map of field metadata with derived properties keyed by field path */

577

fieldMeta: Record<DeepKeys<TFormData>, FieldMeta<any, any, any, ...>>;

578

579

/** Whether the form can be submitted (valid and not submitting) */

580

canSubmit: boolean;

581

582

/** Whether any field has been touched */

583

isTouched: boolean;

584

585

/** Whether the form is in its initial state */

586

isPristine: boolean;

587

588

/** Whether the form has been modified from initial state */

589

isDirty: boolean;

590

591

/** Whether the form is valid (no errors at form or field level) */

592

isValid: boolean;

593

}

594

```

595

596

### FormValidators

597

598

Form-level validator configuration.

599

600

```typescript { .api }

601

interface FormValidators<

602

TFormData,

603

TOnMount extends undefined | FormValidateOrFn<TFormData>,

604

TOnChange extends undefined | FormValidateOrFn<TFormData>,

605

TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,

606

TOnBlur extends undefined | FormValidateOrFn<TFormData>,

607

TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,

608

TOnSubmit extends undefined | FormValidateOrFn<TFormData>,

609

TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,

610

TOnDynamic extends undefined | FormValidateOrFn<TFormData>,

611

TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,

612

TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,

613

> {

614

/** Validator that runs when form is mounted */

615

onMount?: TOnMount;

616

617

/** Validator that runs when form values change */

618

onChange?: TOnChange;

619

620

/** Async validator that runs when form values change */

621

onChangeAsync?: TOnChangeAsync;

622

623

/** Validator that runs when a field is blurred */

624

onBlur?: TOnBlur;

625

626

/** Async validator that runs when a field is blurred */

627

onBlurAsync?: TOnBlurAsync;

628

629

/** Validator that runs on form submission */

630

onSubmit?: TOnSubmit;

631

632

/** Async validator that runs on form submission */

633

onSubmitAsync?: TOnSubmitAsync;

634

635

/** Validator that runs dynamically based on validation logic */

636

onDynamic?: TOnDynamic;

637

638

/** Async validator that runs dynamically based on validation logic */

639

onDynamicAsync?: TOnDynamicAsync;

640

641

/** Server-side validator (used with framework integrations) */

642

onServer?: TOnServer;

643

}

644

```

645

646

### FormListeners

647

648

Event listener configuration for form lifecycle events.

649

650

```typescript { .api }

651

interface FormListeners<TFormData, ...> {

652

/**

653

* Listener called when form is mounted

654

* @param props.formApi - Form API instance

655

*/

656

onMount?: (props: {

657

formApi: FormApi<TFormData, ...>;

658

}) => void;

659

660

/**

661

* Listener called when form values change

662

* @param props.formApi - Form API instance

663

* @param props.fieldApi - Field API that triggered the change

664

*/

665

onChange?: (props: {

666

formApi: FormApi<TFormData, ...>;

667

fieldApi: AnyFieldApi;

668

}) => void;

669

670

/** Debounce time in milliseconds for onChange listener */

671

onChangeDebounceMs?: number;

672

673

/**

674

* Listener called when a field is blurred

675

* @param props.formApi - Form API instance

676

* @param props.fieldApi - Field API that was blurred

677

*/

678

onBlur?: (props: {

679

formApi: FormApi<TFormData, ...>;

680

fieldApi: AnyFieldApi;

681

}) => void;

682

683

/** Debounce time in milliseconds for onBlur listener */

684

onBlurDebounceMs?: number;

685

686

/**

687

* Listener called on form submission

688

* @param props.formApi - Form API instance

689

* @param props.meta - Submit metadata

690

*/

691

onSubmit?: (props: {

692

formApi: FormApi<TFormData, ...>;

693

meta: TSubmitMeta;

694

}) => void;

695

}

696

```

697

698

### Form Validation Types

699

700

```typescript { .api }

701

/**

702

* Synchronous form validation function

703

* @param props.value - Current form values

704

* @param props.formApi - Form API instance

705

* @returns Validation error or undefined if valid

706

*/

707

type FormValidateFn<TFormData> = (props: {

708

value: TFormData;

709

formApi: FormApi<TFormData, ...>;

710

}) => ValidationError | Promise<ValidationError>;

711

712

/**

713

* Asynchronous form validation function with abort signal support

714

* @param props.value - Current form values

715

* @param props.signal - AbortSignal for cancellation

716

* @param props.formApi - Form API instance

717

* @returns Promise resolving to validation error or undefined if valid

718

*/

719

type FormValidateAsyncFn<TFormData> = (props: {

720

value: TFormData;

721

signal: AbortSignal;

722

formApi: FormApi<TFormData, ...>;

723

}) => ValidationError | Promise<ValidationError>;

724

725

/** Union of validation function or Standard Schema validator */

726

type FormValidateOrFn<TFormData> =

727

| FormValidateFn<TFormData>

728

| StandardSchemaV1<TFormData, TFormData>;

729

730

/** Union of async validation function or Standard Schema validator */

731

type FormAsyncValidateOrFn<TFormData> =

732

| FormValidateAsyncFn<TFormData>

733

| StandardSchemaV1<TFormData, TFormData>;

734

```

735

736

### Validation Metadata Types

737

738

Types for tracking validation state and field information.

739

740

```typescript { .api }

741

/**

742

* Validation metadata for tracking async validation state

743

* Stores an abort controller to cancel previous async validation attempts

744

*/

745

type ValidationMeta = {

746

/** AbortController stored in memory to cancel previous async validation attempts */

747

lastAbortController: AbortController;

748

};

749

750

/**

751

* Field information object containing field instance and validation metadata

752

* Accessible via form.fieldInfo[fieldName]

753

*/

754

type FieldInfo<TFormData> = {

755

/** Field API instance or null if field is not currently mounted */

756

instance: FieldApi<TFormData, any, any, ...> | null;

757

758

/** Validation metadata by trigger type for this field */

759

validationMetaMap: Record<ValidationErrorMapKeys, ValidationMeta | undefined>;

760

};

761

```

762

763

## Helper Types

764

765

Type aliases for convenience when working with forms without needing to specify all generic parameters.

766

767

```typescript { .api }

768

/**

769

* FormApi with all generics set to any for convenience in dynamic or loosely-typed contexts

770

* Useful when you need to work with forms of unknown structure

771

*/

772

type AnyFormApi = FormApi<any, any, any, any, any, any, any, any, any, any, any, any>;

773

774

/**

775

* FormState with all generics set to any for convenience

776

* Useful for generic form state handling

777

*/

778

type AnyFormState = FormState<any, any, any, any, any, any, any, any, any, any, any>;

779

780

/**

781

* FormOptions with all generics set to any for convenience

782

* Useful when passing form options dynamically

783

*/

784

type AnyFormOptions = FormOptions<any, any, any, any, any, any, any, any, any, any, any, any>;

785

```

786

787

## Usage Examples

788

789

### Basic Form Creation

790

791

```typescript

792

import { useForm } from '@tanstack/react-form';

793

794

function ContactForm() {

795

const form = useForm({

796

defaultValues: {

797

name: '',

798

email: '',

799

message: '',

800

},

801

validators: {

802

onChange: ({ value }) => {

803

if (!value.email.includes('@')) {

804

return { form: 'Invalid email' };

805

}

806

return undefined;

807

},

808

},

809

onSubmit: async ({ value }) => {

810

await fetch('/api/contact', {

811

method: 'POST',

812

body: JSON.stringify(value),

813

});

814

},

815

});

816

817

return (

818

<form onSubmit={(e) => {

819

e.preventDefault();

820

form.handleSubmit();

821

}}>

822

{/* Field components */}

823

</form>

824

);

825

}

826

```

827

828

### Async Validation with Debouncing

829

830

```typescript

831

const form = useForm({

832

defaultValues: {

833

username: '',

834

},

835

asyncDebounceMs: 500,

836

validators: {

837

onChangeAsync: async ({ value, signal }) => {

838

const response = await fetch(

839

`/api/check-username?username=${value.username}`,

840

{ signal }

841

);

842

const data = await response.json();

843

return data.available ? undefined : 'Username already taken';

844

},

845

},

846

});

847

```

848

849

### Form State Subscription

850

851

```typescript

852

function FormStatus() {

853

const form = useForm({ /* ... */ });

854

855

return (

856

<form.Subscribe

857

selector={(state) => ({

858

canSubmit: state.canSubmit,

859

isSubmitting: state.isSubmitting,

860

errors: state.errors,

861

})}

862

>

863

{({ canSubmit, isSubmitting, errors }) => (

864

<div>

865

<button type="submit" disabled={!canSubmit || isSubmitting}>

866

{isSubmitting ? 'Submitting...' : 'Submit'}

867

</button>

868

{errors.map((error, i) => (

869

<div key={i}>{String(error)}</div>

870

))}

871

</div>

872

)}

873

</form.Subscribe>

874

);

875

}

876

```

877

878

### Array Field Manipulation

879

880

```typescript

881

const form = useForm({

882

defaultValues: {

883

todos: [{ text: '', completed: false }],

884

},

885

});

886

887

// Add new todo

888

form.pushFieldValue('todos', { text: '', completed: false });

889

890

// Remove todo at index

891

form.removeFieldValue('todos', 1);

892

893

// Move todo from index 0 to index 2

894

form.moveFieldValues('todos', 0, 2);

895

896

// Clear all todos

897

form.clearFieldValues('todos');

898

```

899