or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

admin-core.mdadvanced.mdauth.mddata-management.mddetail-views.mdforms-inputs.mdi18n.mdindex.mdlayout-navigation.mdlists-data-display.mdui-components.md

forms-inputs.mddocs/

0

# Forms & Inputs

1

2

React Admin provides a comprehensive form system built on React Hook Form, offering rich input components, validation, and sophisticated form handling capabilities. The system supports complex scenarios including nested forms, arrays, relationships, and multi-step workflows.

3

4

## Form Component

5

6

The `<Form>` component is the foundation of form handling in React Admin, providing form context and validation.

7

8

```typescript { .api }

9

import { Form } from 'react-admin';

10

11

interface FormProps {

12

defaultValues?: any;

13

record?: RaRecord;

14

validate?: ValidateForm;

15

resolver?: any;

16

onSubmit?: (data: any) => void | Promise<void>;

17

sanitizeEmptyValues?: boolean;

18

warnWhenUnsavedChanges?: boolean;

19

noValidate?: boolean;

20

children: React.ReactNode;

21

id?: string;

22

className?: string;

23

sx?: any;

24

}

25

26

const Form: React.FC<FormProps>;

27

28

type ValidateForm = (values: any) => any | Promise<any>;

29

```

30

31

### Form Usage Example

32

33

```typescript

34

import { Form, TextInput, SaveButton } from 'react-admin';

35

36

const PostForm = ({ record, onSave }) => (

37

<Form

38

record={record}

39

onSubmit={onSave}

40

validate={(values) => {

41

const errors: any = {};

42

if (!values.title) errors.title = 'Title is required';

43

if (!values.content) errors.content = 'Content is required';

44

return errors;

45

}}

46

>

47

<TextInput source="title" label="Title" required />

48

<TextInput source="content" label="Content" multiline rows={4} />

49

<SaveButton />

50

</Form>

51

);

52

```

53

54

## Text Inputs

55

56

### TextInput

57

58

Basic text input for single-line text.

59

60

```typescript { .api }

61

import { TextInput } from 'react-admin';

62

63

interface TextInputProps {

64

source: string;

65

label?: string | false;

66

helperText?: string | false;

67

defaultValue?: any;

68

format?: (value: any) => any;

69

parse?: (value: any) => any;

70

validate?: Function | Function[];

71

required?: boolean;

72

disabled?: boolean;

73

readOnly?: boolean;

74

multiline?: boolean;

75

rows?: number;

76

maxRows?: number;

77

type?: 'text' | 'email' | 'url' | 'tel' | 'password';

78

placeholder?: string;

79

fullWidth?: boolean;

80

margin?: 'none' | 'dense' | 'normal';

81

variant?: 'standard' | 'outlined' | 'filled';

82

InputProps?: any;

83

inputProps?: any;

84

className?: string;

85

sx?: any;

86

}

87

88

const TextInput: React.FC<TextInputProps>;

89

```

90

91

#### Usage Examples

92

93

```typescript

94

// Basic text input

95

<TextInput source="title" label="Post Title" />

96

97

// Multiline text input

98

<TextInput source="content" label="Content" multiline rows={4} />

99

100

// Email input with validation

101

<TextInput

102

source="email"

103

label="Email"

104

type="email"

105

validate={[required(), email()]}

106

/>

107

108

// Password input

109

<TextInput source="password" label="Password" type="password" />

110

111

// Custom format and parse

112

<TextInput

113

source="slug"

114

format={value => value?.toLowerCase().replace(/\s+/g, '-')}

115

parse={value => value?.toLowerCase().replace(/\s+/g, '-')}

116

/>

117

```

118

119

### NumberInput

120

121

Numeric input with number formatting and validation.

122

123

```typescript { .api }

124

import { NumberInput } from 'react-admin';

125

126

interface NumberInputProps extends Omit<TextInputProps, 'type'> {

127

min?: number;

128

max?: number;

129

step?: number;

130

}

131

132

const NumberInput: React.FC<NumberInputProps>;

133

```

134

135

#### Usage Example

136

137

```typescript

138

<NumberInput

139

source="price"

140

label="Price"

141

min={0}

142

step={0.01}

143

validate={[required(), minValue(0)]}

144

/>

145

```

146

147

### PasswordInput

148

149

Password input with show/hide toggle.

150

151

```typescript { .api }

152

import { PasswordInput } from 'react-admin';

153

154

const PasswordInput: React.FC<TextInputProps>;

155

```

156

157

## Selection Inputs

158

159

### SelectInput

160

161

Dropdown selection for choosing from predefined options.

162

163

```typescript { .api }

164

import { SelectInput } from 'react-admin';

165

166

interface SelectInputProps {

167

source: string;

168

choices: ChoiceType[];

169

optionText?: string | Function;

170

optionValue?: string;

171

translateChoice?: boolean;

172

disableValue?: string | Function;

173

emptyText?: string;

174

emptyValue?: any;

175

label?: string | false;

176

validate?: Function | Function[];

177

defaultValue?: any;

178

fullWidth?: boolean;

179

margin?: 'none' | 'dense' | 'normal';

180

variant?: 'standard' | 'outlined' | 'filled';

181

className?: string;

182

sx?: any;

183

}

184

185

interface ChoiceType {

186

id: any;

187

name?: string;

188

[key: string]: any;

189

}

190

191

const SelectInput: React.FC<SelectInputProps>;

192

```

193

194

#### Usage Example

195

196

```typescript

197

const statusChoices = [

198

{ id: 'draft', name: 'Draft' },

199

{ id: 'published', name: 'Published' },

200

{ id: 'archived', name: 'Archived' }

201

];

202

203

<SelectInput

204

source="status"

205

choices={statusChoices}

206

label="Status"

207

defaultValue="draft"

208

/>

209

```

210

211

### AutocompleteInput

212

213

Autocomplete input with search and filtering.

214

215

```typescript { .api }

216

import { AutocompleteInput } from 'react-admin';

217

218

interface AutocompleteInputProps {

219

source: string;

220

choices: ChoiceType[];

221

optionText?: string | Function;

222

optionValue?: string;

223

matchSuggestion?: Function;

224

shouldRenderSuggestions?: Function;

225

inputText?: Function;

226

setFilter?: Function;

227

filterToQuery?: Function;

228

freeSolo?: boolean;

229

multiple?: boolean;

230

clearOnBlur?: boolean;

231

onCreate?: Function;

232

createLabel?: string;

233

createItemLabel?: string;

234

noOptionsText?: string;

235

label?: string | false;

236

validate?: Function | Function[];

237

debounce?: number;

238

className?: string;

239

sx?: any;

240

}

241

242

const AutocompleteInput: React.FC<AutocompleteInputProps>;

243

```

244

245

#### Usage Example

246

247

```typescript

248

const tagChoices = [

249

{ id: 1, name: 'Technology' },

250

{ id: 2, name: 'React' },

251

{ id: 3, name: 'JavaScript' }

252

];

253

254

<AutocompleteInput

255

source="tags"

256

choices={tagChoices}

257

multiple

258

create

259

label="Tags"

260

onCreate={(filter) => {

261

const newTag = { id: Date.now(), name: filter };

262

// Add to choices or save to backend

263

return newTag;

264

}}

265

/>

266

```

267

268

### RadioButtonGroupInput

269

270

Radio button group for single selection.

271

272

```typescript { .api }

273

import { RadioButtonGroupInput } from 'react-admin';

274

275

interface RadioButtonGroupInputProps {

276

source: string;

277

choices: ChoiceType[];

278

optionText?: string | Function;

279

optionValue?: string;

280

translateChoice?: boolean;

281

label?: string | false;

282

validate?: Function | Function[];

283

row?: boolean;

284

className?: string;

285

sx?: any;

286

}

287

288

const RadioButtonGroupInput: React.FC<RadioButtonGroupInputProps>;

289

```

290

291

### CheckboxGroupInput

292

293

Checkbox group for multiple selection.

294

295

```typescript { .api }

296

import { CheckboxGroupInput } from 'react-admin';

297

298

interface CheckboxGroupInputProps {

299

source: string;

300

choices: ChoiceType[];

301

optionText?: string | Function;

302

optionValue?: string;

303

translateChoice?: boolean;

304

label?: string | false;

305

validate?: Function | Function[];

306

row?: boolean;

307

className?: string;

308

sx?: any;

309

}

310

311

const CheckboxGroupInput: React.FC<CheckboxGroupInputProps>;

312

```

313

314

## Boolean Inputs

315

316

### BooleanInput

317

318

Checkbox for boolean values.

319

320

```typescript { .api }

321

import { BooleanInput } from 'react-admin';

322

323

interface BooleanInputProps {

324

source: string;

325

label?: string | false;

326

helperText?: string | false;

327

defaultValue?: boolean;

328

format?: (value: any) => boolean;

329

parse?: (value: boolean) => any;

330

validate?: Function | Function[];

331

disabled?: boolean;

332

readOnly?: boolean;

333

color?: 'primary' | 'secondary' | 'default';

334

size?: 'small' | 'medium';

335

className?: string;

336

sx?: any;

337

}

338

339

const BooleanInput: React.FC<BooleanInputProps>;

340

```

341

342

### NullableBooleanInput

343

344

Three-state boolean input (true/false/null).

345

346

```typescript { .api }

347

import { NullableBooleanInput } from 'react-admin';

348

349

const NullableBooleanInput: React.FC<SelectInputProps>;

350

```

351

352

#### Usage Example

353

354

```typescript

355

<NullableBooleanInput

356

source="featured"

357

label="Featured"

358

nullLabel="Not Set"

359

falseLabel="No"

360

trueLabel="Yes"

361

/>

362

```

363

364

## Date and Time Inputs

365

366

### DateInput

367

368

Date picker input.

369

370

```typescript { .api }

371

import { DateInput } from 'react-admin';

372

373

interface DateInputProps {

374

source: string;

375

label?: string | false;

376

validate?: Function | Function[];

377

defaultValue?: Date | string;

378

format?: string;

379

parse?: (value: any) => any;

380

disabled?: boolean;

381

readOnly?: boolean;

382

fullWidth?: boolean;

383

margin?: 'none' | 'dense' | 'normal';

384

variant?: 'standard' | 'outlined' | 'filled';

385

className?: string;

386

sx?: any;

387

}

388

389

const DateInput: React.FC<DateInputProps>;

390

```

391

392

### DateTimeInput

393

394

Combined date and time picker.

395

396

```typescript { .api }

397

import { DateTimeInput } from 'react-admin';

398

399

const DateTimeInput: React.FC<DateInputProps>;

400

```

401

402

### TimeInput

403

404

Time picker input.

405

406

```typescript { .api }

407

import { TimeInput } from 'react-admin';

408

409

const TimeInput: React.FC<DateInputProps>;

410

```

411

412

#### Usage Examples

413

414

```typescript

415

// Date input

416

<DateInput source="publishedAt" label="Published Date" />

417

418

// DateTime input with validation

419

<DateTimeInput

420

source="eventDate"

421

label="Event Date & Time"

422

validate={[required(), minValue(new Date())]}

423

/>

424

425

// Time input

426

<TimeInput source="reminderTime" label="Reminder Time" />

427

```

428

429

## File and Media Inputs

430

431

### FileInput

432

433

File upload input with preview capabilities.

434

435

```typescript { .api }

436

import { FileInput } from 'react-admin';

437

438

interface FileInputProps {

439

source: string;

440

accept?: string;

441

multiple?: boolean;

442

maxSize?: number;

443

minSize?: number;

444

placeholder?: React.ReactNode;

445

children?: React.ReactNode;

446

options?: any;

447

label?: string | false;

448

validate?: Function | Function[];

449

className?: string;

450

sx?: any;

451

}

452

453

const FileInput: React.FC<FileInputProps>;

454

```

455

456

### ImageInput

457

458

Specialized file input for images with preview.

459

460

```typescript { .api }

461

import { ImageInput } from 'react-admin';

462

463

const ImageInput: React.FC<FileInputProps>;

464

```

465

466

#### Usage Examples

467

468

```typescript

469

// Basic file input

470

<FileInput source="document" label="Upload Document">

471

<FileField source="src" title="title" />

472

</FileInput>

473

474

// Image input with preview

475

<ImageInput source="image" label="Product Image" accept="image/*">

476

<ImageField source="src" title="title" />

477

</ImageInput>

478

479

// Multiple file upload

480

<FileInput

481

source="attachments"

482

label="Attachments"

483

multiple

484

accept="application/pdf,image/*"

485

>

486

<FileField source="src" title="title" />

487

</FileInput>

488

```

489

490

## Relationship Inputs

491

492

### ReferenceInput

493

494

Input for selecting related records.

495

496

```typescript { .api }

497

import { ReferenceInput } from 'react-admin';

498

499

interface ReferenceInputProps {

500

source: string;

501

reference: string;

502

children: React.ReactElement;

503

sort?: { field: string; order: 'ASC' | 'DESC' };

504

filter?: any;

505

perPage?: number;

506

enableGetChoices?: Function;

507

label?: string | false;

508

validate?: Function | Function[];

509

className?: string;

510

sx?: any;

511

}

512

513

const ReferenceInput: React.FC<ReferenceInputProps>;

514

```

515

516

#### Usage Example

517

518

```typescript

519

<ReferenceInput source="categoryId" reference="categories">

520

<SelectInput optionText="name" />

521

</ReferenceInput>

522

523

// With autocomplete

524

<ReferenceInput source="authorId" reference="users" sort={{ field: 'name', order: 'ASC' }}>

525

<AutocompleteInput optionText="name" />

526

</ReferenceInput>

527

```

528

529

### ReferenceArrayInput

530

531

Input for selecting multiple related records.

532

533

```typescript { .api }

534

import { ReferenceArrayInput } from 'react-admin';

535

536

interface ReferenceArrayInputProps {

537

source: string;

538

reference: string;

539

children: React.ReactElement;

540

sort?: { field: string; order: 'ASC' | 'DESC' };

541

filter?: any;

542

perPage?: number;

543

label?: string | false;

544

validate?: Function | Function[];

545

className?: string;

546

sx?: any;

547

}

548

549

const ReferenceArrayInput: React.FC<ReferenceArrayInputProps>;

550

```

551

552

#### Usage Example

553

554

```typescript

555

<ReferenceArrayInput source="tagIds" reference="tags">

556

<AutocompleteInput optionText="name" />

557

</ReferenceArrayInput>

558

```

559

560

## Array and Complex Inputs

561

562

### ArrayInput

563

564

Input for editing arrays of objects.

565

566

```typescript { .api }

567

import { ArrayInput } from 'react-admin';

568

569

interface ArrayInputProps {

570

source: string;

571

label?: string | false;

572

validate?: Function | Function[];

573

children: React.ReactElement;

574

className?: string;

575

sx?: any;

576

}

577

578

const ArrayInput: React.FC<ArrayInputProps>;

579

```

580

581

#### Usage Example

582

583

```typescript

584

import { ArrayInput, SimpleFormIterator, TextInput, NumberInput } from 'react-admin';

585

586

<ArrayInput source="items" label="Order Items">

587

<SimpleFormIterator>

588

<TextInput source="name" label="Item Name" />

589

<NumberInput source="quantity" label="Quantity" />

590

<NumberInput source="price" label="Price" />

591

</SimpleFormIterator>

592

</ArrayInput>

593

```

594

595

## Form Hooks

596

597

### useInput

598

599

Access and control individual input state.

600

601

```typescript { .api }

602

import { useInput } from 'react-admin';

603

604

interface UseInputOptions {

605

defaultValue?: any;

606

format?: (value: any) => any;

607

parse?: (value: any) => any;

608

validate?: Function | Function[];

609

onBlur?: Function;

610

onChange?: Function;

611

source: string;

612

}

613

614

interface UseInputResult {

615

field: {

616

name: string;

617

value: any;

618

onChange: (event: any) => void;

619

onBlur: (event: any) => void;

620

};

621

fieldState: {

622

invalid: boolean;

623

isTouched: boolean;

624

isDirty: boolean;

625

error?: any;

626

};

627

formState: {

628

isSubmitted: boolean;

629

isSubmitting: boolean;

630

isValid: boolean;

631

errors: any;

632

};

633

}

634

635

const useInput: (options: UseInputOptions) => UseInputResult;

636

```

637

638

#### Usage Example

639

640

```typescript

641

import { useInput } from 'react-admin';

642

643

const CustomInput = ({ source, label, ...props }) => {

644

const {

645

field,

646

fieldState: { error, invalid, isTouched },

647

formState: { isSubmitted }

648

} = useInput({ source, ...props });

649

650

return (

651

<div>

652

<label>{label}</label>

653

<input {...field} />

654

{((isTouched && invalid) || (isSubmitted && invalid)) && (

655

<span style={{ color: 'red' }}>{error?.message}</span>

656

)}

657

</div>

658

);

659

};

660

```

661

662

### useForm

663

664

Access form state and methods.

665

666

```typescript { .api }

667

import { useForm } from 'react-admin';

668

669

const useForm: () => {

670

getValues: (names?: string | string[]) => any;

671

setValue: (name: string, value: any, options?: any) => void;

672

reset: (values?: any) => void;

673

watch: (name?: string | string[], defaultValue?: any) => any;

674

formState: FormState;

675

control: Control;

676

register: Function;

677

handleSubmit: Function;

678

clearErrors: Function;

679

setError: Function;

680

trigger: Function;

681

};

682

```

683

684

## Validation

685

686

React Admin provides comprehensive validation capabilities.

687

688

### Built-in Validators

689

690

```typescript { .api }

691

import {

692

required,

693

minLength,

694

maxLength,

695

minValue,

696

maxValue,

697

number,

698

regex,

699

email,

700

choices

701

} from 'react-admin';

702

703

// Validation function types

704

type ValidatorFunction = (value: any, allValues?: any, props?: any) => string | undefined;

705

706

const required: (message?: string) => ValidatorFunction;

707

const minLength: (min: number, message?: string) => ValidatorFunction;

708

const maxLength: (max: number, message?: string) => ValidatorFunction;

709

const minValue: (min: number, message?: string) => ValidatorFunction;

710

const maxValue: (max: number, message?: string) => ValidatorFunction;

711

const number: (message?: string) => ValidatorFunction;

712

const regex: (pattern: RegExp, message?: string) => ValidatorFunction;

713

const email: (message?: string) => ValidatorFunction;

714

const choices: (list: any[], message?: string) => ValidatorFunction;

715

```

716

717

### Validation Examples

718

719

```typescript

720

import { required, minLength, maxLength, email, minValue } from 'react-admin';

721

722

// Single validator

723

<TextInput source="title" validate={required()} />

724

725

// Multiple validators

726

<TextInput

727

source="description"

728

validate={[required(), minLength(10), maxLength(500)]}

729

/>

730

731

// Email validation

732

<TextInput source="email" validate={[required(), email()]} />

733

734

// Number validation

735

<NumberInput

736

source="price"

737

validate={[required(), minValue(0)]}

738

/>

739

740

// Custom validation

741

<TextInput

742

source="username"

743

validate={(value) => {

744

if (!value) return 'Username is required';

745

if (value.length < 3) return 'Username must be at least 3 characters';

746

if (!/^[a-zA-Z0-9_]+$/.test(value)) return 'Username can only contain letters, numbers, and underscores';

747

return undefined;

748

}}

749

/>

750

```

751

752

### Async Validation

753

754

```typescript

755

const asyncValidate = async (value) => {

756

if (!value) return 'Required';

757

758

const response = await fetch(`/api/check-username?username=${value}`);

759

const result = await response.json();

760

761

if (!result.available) {

762

return 'Username is already taken';

763

}

764

765

return undefined;

766

};

767

768

<TextInput source="username" validate={asyncValidate} />

769

```

770

771

## Advanced Form Features

772

773

### FormDataConsumer

774

775

Access and react to form data changes.

776

777

```typescript { .api }

778

import { FormDataConsumer } from 'react-admin';

779

780

interface FormDataConsumerProps {

781

children: (formDataConsumerProps: FormDataConsumerRenderParams) => React.ReactNode;

782

}

783

784

interface FormDataConsumerRenderParams {

785

formData: any;

786

scopedFormData?: any;

787

getSource?: (source: string) => string;

788

}

789

790

const FormDataConsumer: React.FC<FormDataConsumerProps>;

791

```

792

793

#### Usage Example

794

795

```typescript

796

import { FormDataConsumer, SelectInput, TextInput } from 'react-admin';

797

798

<FormDataConsumer>

799

{({ formData, ...rest }) => (

800

<>

801

<SelectInput source="type" choices={typeChoices} {...rest} />

802

{formData.type === 'book' && (

803

<TextInput source="isbn" label="ISBN" {...rest} />

804

)}

805

{formData.type === 'movie' && (

806

<TextInput source="director" label="Director" {...rest} />

807

)}

808

</>

809

)}

810

</FormDataConsumer>

811

```

812

813

### Conditional Fields

814

815

```typescript

816

import { FormDataConsumer, BooleanInput, TextInput } from 'react-admin';

817

818

const ConditionalFieldsExample = () => (

819

<>

820

<BooleanInput source="hasDiscount" label="Has Discount" />

821

<FormDataConsumer>

822

{({ formData }) =>

823

formData.hasDiscount && (

824

<NumberInput

825

source="discountPercentage"

826

label="Discount %"

827

min={0}

828

max={100}

829

/>

830

)

831

}

832

</FormDataConsumer>

833

</>

834

);

835

```

836

837

### Form Sections and Layouts

838

839

```typescript

840

import {

841

Form,

842

TextInput,

843

NumberInput,

844

TabbedForm,

845

FormTab,

846

Toolbar,

847

SaveButton,

848

DeleteButton

849

} from 'react-admin';

850

851

const ProductForm = () => (

852

<TabbedForm>

853

<FormTab label="General">

854

<TextInput source="name" label="Product Name" />

855

<NumberInput source="price" label="Price" />

856

<TextInput source="description" multiline rows={4} />

857

</FormTab>

858

859

<FormTab label="Inventory">

860

<NumberInput source="stock" label="Stock Quantity" />

861

<NumberInput source="minStock" label="Minimum Stock" />

862

<BooleanInput source="trackInventory" label="Track Inventory" />

863

</FormTab>

864

865

<FormTab label="SEO">

866

<TextInput source="metaTitle" label="Meta Title" />

867

<TextInput source="metaDescription" label="Meta Description" multiline />

868

<TextInput source="slug" label="URL Slug" />

869

</FormTab>

870

871

<Toolbar>

872

<SaveButton />

873

<DeleteButton />

874

</Toolbar>

875

</TabbedForm>

876

);

877

```

878

879

React Admin's form system provides powerful, flexible form handling with rich validation, sophisticated input components, and excellent developer experience for building complex data entry interfaces.