Form.io provides a component library that goes far beyond standard HTML form elements in its drag and drop form builder. Text fields, checkboxes, and dropdowns are table stakes. The real value comes from components that solve enterprise problems: file uploads to your storage provider, nested forms for reusable data structures, data grids that enable end users to add and remove additional rows of repeatable fields, signature capture for compliance, and the ability to build entirely custom components when the built-in options are not enough.
Every component in Form.io is JSON-driven. The form schema defines what components exist, how they behave, and what validation they enforce. This architecture means components work identically whether rendered in a browser, a mobile app, or processed server-side. When you need functionality that does not exist, you extend the base classes and register your custom component with the renderer.
Component Categories
Form.io organizes components into five categories, each serving distinct purposes in form construction.
Basic Components cover standard data entry: text fields, text areas, numbers, passwords, checkboxes, select boxes, radio buttons, and buttons. These map closely to native HTML form elements but include Form.io’s validation, conditional logic, and data binding.
Advanced Components handle specialized input: email fields with format validation, URLs, phone numbers with input masks, tags, addresses with provider integration, date/time pickers, day selectors, time inputs, currency fields, and the Survey component for matrix-style questions.
Layout Components structure the form visually without capturing data: HTML content blocks, panels for grouping fields, columns for side-by-side layout, field sets, tables, tabs for organizing long forms, and the Well component for visual separation.
Data Components manage complex data structures: Hidden fields for metadata, Containers for grouping related fields under a single key, Data Grids for tabular repeating rows, Edit Grids for row-by-row editing workflows, and Data Maps for key-value pair collection.
Premium Components provide enterprise functionality that requires additional configuration or licensing: reCAPTCHA for bot protection, File upload with storage provider integration, Nested Forms for reusability, Tagpad for image annotation, Sketchpad for drawing, Signature for digital signing, and Custom components for bespoke implementations.
The Form Components documentation provides the complete reference for each component type.
Premium Components in Detail
Premium components solve problems that basic HTML form elements cannot address. They require more setup but enable workflows that would otherwise need custom development.
File Upload
The File component handles uploads to external storage providers. Form.io does not store uploaded files itself. Instead, files go directly to your configured provider: Amazon S3, Azure Blob Storage, Google Cloud Storage, Dropbox, or a custom URL endpoint.
This architecture matters for compliance and data governance. Files containing sensitive data never pass through Form.io’s servers. They upload directly from the browser to your storage, and Form.io stores only a reference. The File Storage documentation explains provider configuration.
File component settings control allowed file types, maximum size, multiple file uploads, image-specific options like webcam capture, and whether to store files as base64 (useful for small files that should embed in submission data rather than link externally).
Nested Forms
The Nested Form component embeds one form inside another. A “Contact Information” form with name, email, phone, and address fields can be created once and nested into multiple parent forms: job applications, support tickets, account registrations. Changes to the child form propagate to all parents.
This solves the form duplication problem. Instead of copying fields across forms and maintaining them separately, you maintain one child form. The Nested Forms documentation covers the two storage modes.
With “Save as Reference” disabled, child form data merges into the parent submission. The submission contains all fields flattened together.
With “Save as Reference” enabled, the child form creates its own submission, and the parent stores only a reference ID. This is useful when the child data should exist independently, like selecting an existing customer record rather than creating new contact information each time.
Nested forms can contain nested forms, up to five levels deep. Beyond that depth, the platform rejects submissions. This limit exists because deeply nested structures create performance and complexity problems that usually indicate a data modeling issue.
Signature
The Signature component captures digital signatures via mouse, touch, or stylus input. The signature renders as a canvas element where users draw, and the result stores as a base64-encoded PNG image.
For compliance workflows requiring legally binding signatures, Form.io integrates with eSignature providers like DocuSign. The signature component can trigger provider-specific workflows that send documents for formal signing rather than just capturing a drawn image. The eSign Integrations documentation covers provider setup.
Basic signature capture is sufficient for acknowledgment forms, consent capture, or internal approval workflows where legal enforceability is not required.
For when you need to prove a decision was made and have legal enforceability, ask us about E-Sign+: Compliance-ready, zero-trust, deployed in-suite, API-driven digital signatures.
reCAPTCHA
The reCAPTCHA component integrates Google’s reCAPTCHA v3 for bot protection. Unlike earlier reCAPTCHA versions that required users to click checkboxes or identify images, v3 runs invisibly and returns a score indicating how likely the interaction is from a human.
Configuration requires a Site Key and Secret Key from the Google reCAPTCHA admin panel, entered in your Form.io project settings under Integrations. The component can trigger on form load or on button click, capturing the reCAPTCHA response in the submission metadata.
The score (0.0 to 1.0) helps you decide what to do with submissions. A score of 0.9 suggests a human; a score of 0.1 suggests a bot. Your application logic determines the threshold and response. The reCAPTCHA example demonstrates both trigger modes.
Tagpad and Sketchpad
Tagpad lets users annotate images by clicking points and associating form fields with each point. An equipment inspection form might display a machine diagram where users tap locations to report issues, entering details for each tagged point.
Sketchpad provides freeform drawing capabilities, useful for capturing diagrams, markups, or illustrations that structured form fields cannot represent.
Both components store their data as JSON structures containing coordinates and associated values, which can be processed programmatically or displayed visually in reports.
Data Table
The Data Table component fetches data from external sources and presents it for user selection. Unlike the Select component which provides a dropdown, Data Table displays a full table view with sorting and filtering, suitable for selecting from larger datasets.
Review Page
The Review Page component displays a summary of all entered data before submission, giving users a chance to verify their inputs. This is particularly useful in Multi-Page Form Wizards where users might not remember what they entered on earlier pages.
Data Grids and Edit Grids
Data components deserve special attention because they enable repeating data structures that basic HTML forms handle poorly.
Data Grid presents a table where each column is a component and users can add rows. A line-item order form with product, quantity, and price columns uses Data Grid. Rows appear as a table, and users click “Add Another” to append rows.
Edit Grid provides similar functionality but with a different interaction model. Instead of editing directly in table cells, users click to open a row, edit fields in a form layout, then save the row back to the table view. This works better for rows with many fields or complex layouts that do not fit well in table columns.
Both components store data as arrays of objects, where each object contains the row’s field values. The Edit Grid example demonstrates customizing the display templates for headers and rows.
The choice between Data Grid and Edit Grid depends on data complexity. Simple rows with few fields work well in Data Grid’s inline editing. Complex rows with many fields, conditional logic, or nested structures work better in Edit Grid’s modal editing approach.
Building Custom Components
When built-in components do not meet your requirements, custom components let you extend Form.io with new functionality. The process involves creating a JavaScript class that extends a base component, implementing required methods, and registering the component with the renderer.
Every custom component extends a base class. Choose the base that most closely matches your desired behavior:
Componentfor basic single-value inputsFieldfor standard field behavior with labels and validationInputfor text-style inputsMultivaluefor components that can hold arrays- Or any existing component if you’re modifying specific behavior
The Custom Components documentation walks through the process. The essential methods to implement are:
static schema() returns the default JSON schema for the component, defining its type and default properties.
static builderInfo provides metadata for the form builder: title, icon, which group it appears in, and weight for ordering.
render() returns the HTML string that displays the component. Use Form.io’s template system for consistency with other components.
attach(element) runs after rendering to attach event listeners and set up interactive behavior.
getValue() and setValue(value) handle reading from and writing to the component’s value.
The Contributed Components repository provides working examples including a Rating component and Check Matrix. These demonstrate patterns for handling user interaction, managing state, and integrating with Form.io’s validation and data systems.
Registering Custom Components
Custom components register with the renderer through modules:
import CustomComponent from './CustomComponent';
Formio.use({
components: {
customcomponent: CustomComponent
}
});
After registration, the component appears in the form builder and can be used like any built-in component. The type in your schema must match the key used during registration.
For components that should appear in the builder’s component panel, the builderInfo static property controls placement:
static builderInfo = {
title: 'Custom Rating',
group: 'basic',
icon: 'star',
weight: 70,
schema: CustomComponent.schema()
}
The group determines which panel section contains the component. The weight controls ordering within that section.
Custom Component Limitations
Custom components run client-side in the renderer. They do not automatically gain server-side validation. If your component requires server-side validation logic, you need to implement that separately through webhooks or custom API middleware.
Custom components also require distribution. Every application that renders forms with your custom component must include the component code. This is straightforward for applications you control but requires coordination for forms that might render in third-party contexts.
The Modules documentation explains how to package custom components for distribution and reuse.
Component Settings Architecture
Every Form.io component shares a common settings structure, accessible through tabs in the form builder:
Display controls visual presentation: label, placeholder, description, tooltip, custom CSS classes, and layout options.
Data manages values: default value, multiple values, calculated values, and data storage options including whether to persist the field.
Validation defines rules: required, minimum/maximum length or value, pattern matching, custom validation, and error messages. See Form Validation & Conditional Logic for details.
API configures the data model: property name (the key in submission JSON), tags for categorization, and custom properties for metadata.
Conditional controls visibility based on other fields. Simple conditions use a point-and-click interface; advanced conditions use JavaScript or JSON Logic.
Logic defines triggers and actions that modify component behavior dynamically: changing properties, setting values, or merging schema based on conditions.
This consistent structure means learning one component teaches you the patterns for all components. Custom components that follow the same structure integrate seamlessly with the builder interface.
Styling Components
Form.io components render with CSS classes that you can target for custom styling. Customize With CSS explains the approach in detail, but the key point is that Form.io does not use iframes. Components render directly in your page’s DOM, inheriting your CSS and allowing complete visual customization.
The renderer supports multiple CSS frameworks through template sets. Bootstrap is the default, but templates exist for Semantic UI and other frameworks. You can also create custom templates for complete control over HTML structure.
When to Build Custom vs. Configure Existing
Before building a custom component, verify that configuration cannot solve your problem. Form.io’s built-in components have extensive settings that often enable unexpected use cases.
The Select component can fetch data from external APIs, filter dynamically, and use custom templates. The Hidden component can contain calculated values that drive logic elsewhere. Layout components can create complex visual structures. Conditional logic can show, hide, and modify components dynamically.
Custom components are appropriate when you need:
- Fundamentally different UI interactions (like the Rating component’s star display)
- Integration with external libraries (like a custom charting component)
- Domain-specific widgets that have no analog in standard form elements
- Performance optimization for specialized data entry patterns
Custom components are unnecessary when you need:
- Validation rules (use custom validation instead)
- Visual styling (use CSS instead)
- Conditional behavior (use the Logic system instead)
- Data transformation (use calculated values instead)
The built-in configuration options handle most requirements. Custom components should be reserved for genuinely novel functionality.
Related Resources
- Form Components Documentation: Complete reference for all component types
- Premium Components Documentation: Details on enterprise components
- Custom Components Documentation: Guide to building your own components
- Contributed Components Repository: Working examples of custom components
- formio.js Source Code: Implementation of all built-in components
- Form Validation & Conditional Logic: Configuring component behavior through rules
- Customize With CSS: Styling components to match your application
