Most form platforms treat reporting as an afterthought. You collect data through forms, export it to CSV, and hope your analysts can make sense of it in Excel. Form.io takes a different approach: the same MongoDB database that stores your submissions also powers a sophisticated reporting engine that can join data across forms, calculate derived values, aggregate by groups, and produce embeddable report interfaces for your application users.
The Reporting Module sits on top of MongoDB’s aggregation pipeline, exposing its full power through a configuration interface rather than raw query syntax. You define source forms, field relationships, calculated columns, and aggregation logic through a wizard. The module generates the pipeline stages behind the scenes and produces a report grid that can be filtered, sorted, paginated, and exported.
If you think about it as a tool that merely produces reports, that wouldn’t be sufficient. It wouldn’t even be sufficient to call it a dashboard builder. More accurately, it’s data analysis infrastructure that treats reports as first-class objects you can embed directly into your applications.
For a simplified overview of how it works, click here. For a deeper dive, keep reading.
What the Reporting Module Actually Does
The Reporting Module solves a specific problem: you have submission data spread across multiple forms and resources within a Form.io project, and you need to analyze that data without exporting it to external tools or writing custom aggregation queries.
Consider an HR application with separate forms for Employee records, Department information, Salary data, and Employee Evaluations. Each form captures different aspects of the same underlying entities, linked by common fields like Department ID or Employee ID. The Reporting Module lets you join submissions across all four forms, calculate metrics like average salary per department or employee tenure in months, group results by department, and present the output in a sortable, filterable grid.
The key capabilities include:
Multi-form joins. Connect submissions from different forms based on shared field values. An Employee form and an Evaluation form both reference the same Employee ID, so the module can combine their data into unified report rows.
Calculated columns. Create new data columns using MongoDB aggregation operators: concatenate strings, calculate date differences, perform arithmetic, count array items. These calculations happen at query time on the actual submission data.
Group aggregation. Apply MongoDB’s $group operator to summarize data: count submissions per category, average numeric fields within groups, find min/max values. This transforms row-level submission data into summary statistics.
Embeddable report interface. Reports render as interactive grids with pagination, column sorting, row selection, and filtering. Users can show/hide columns, apply filters, and export selected rows to CSV or PDF.
Custom actions. Define JavaScript actions that execute against selected report rows. Update submission status, trigger workflows, or call external APIs based on user selections.
The MongoDB Foundation
Understanding why the Reporting Module works requires understanding Form.io’s data architecture. Every submission is a JSON document stored in MongoDB. The form schema defines the data structure, and submissions conform to that structure with all the flexibility MongoDB provides for nested objects and arrays.
MongoDB’s aggregation pipeline is a framework for data processing that passes documents through sequential stages. Each stage transforms the documents: filtering ($match), grouping ($group), joining ($lookup), projecting fields ($project), sorting ($sort), and dozens more operations. Complex data analysis that would require multiple SQL queries with temporary tables happens in a single pipeline.
The Reporting Module translates your configuration into aggregation pipeline stages. When you define a form connection, it generates a $lookup stage. Calculated columns become $addFields with expression operators. Group aggregations produce $group stages with accumulators. The visual interface abstracts the syntax while preserving access to the underlying operations.
This matters because MongoDB’s aggregation framework is genuinely powerful. The operators available through the Reporting Module include date arithmetic ($dateDiff, $dayOfWeek, $month), string manipulation ($concat), mathematical operations ($multiply, $divide, $sum), array operations ($size), and group accumulators ($avg, $min, $max, $count). You get real analytical capability, not just filtering and sorting.
Building a Report: The Configuration Flow
Report creation follows a wizard-style interface with distinct configuration sections. Each section maps to a different aspect of the underlying aggregation pipeline.
Basic Settings define the report’s identity and display parameters. You set a title, API path, items per page for pagination, cell width limits, and whether to cache query results. Caching improves performance for expensive aggregations but delays visibility of new submissions.
Source Forms select which forms and resources contribute data to the report. You can choose one form for simple reports or multiple forms for cross-form analysis. When you select multiple forms, the interface prompts you to define connections between them.
Form Connections specify how to join submissions across forms. You identify a Base Form and a Joining Form, then map the connecting fields whose values should match. If your Employee form stores a Department field that references the Department resource’s ID, you connect those fields so employee submissions join with their corresponding department data. For complex structures where the connecting value is nested within an object, you specify the path to the value.
Calculated Columns add derived fields that do not exist in the source forms. You select a MongoDB operator and configure its arguments. To create a full name column, you use Concatenate Strings with First Name and Last Name as arguments. To calculate employee tenure, you use Date Difference between Start Date and today, returning the result in months. Each calculated column becomes available for display, filtering, and further calculations.
Aggregation transforms row-level data into grouped summaries. You select fields to group by, then define calculated columns that operate on groups rather than rows. Group operators include Count (number of submissions per group), Sum (total of a numeric field), Average, Min, and Max. An aggregated report showing department-level statistics would group by Department Name and calculate Total Employees (Count), Average Salary (Average of a calculated salary column), and Average Evaluation Score (Average of evaluation score field).
Columns determines which fields appear in the report grid and their display order. You select from source form fields and calculated columns, set display titles, and define which columns are visible by default versus available through the column picker.
Reporting Controls configures the interactive elements of the embedded report. You can enable a control panel with custom filters, column visibility toggles, and action buttons. Filter configurations specify which fields are filterable and what filter types apply (text search, numeric comparison, date ranges).
Controls Actions defines operations users can perform on selected report rows. Built-in actions include Export to CSV and Download to PDF. Custom actions execute JavaScript code against selected submissions, enabling workflows like updating submission status, triggering notifications, or calling external services.
What Reports Cannot Do
The Reporting Module has meaningful constraints that affect how you structure your data and reports.
Reports only span a single project. You cannot join forms from different Form.io projects into one report. If your architecture uses separate projects for different applications or tenants, reporting stays within project boundaries. Cross-project analysis requires exporting data and using external tools.
Complex nested structures require careful handling. Fields inside Edit Grids and Data Grids (array-based repeating components) were historically unavailable for reporting. As of API server version 9.3.0, the module uses MongoDB’s $unwind operation to support these structures, but you should verify your server version and test with your specific form designs.
Date component types matter. Form.io offers multiple date/time components with different data storage formats. The Date/Time component stores ISO-formatted dates, while the Textfield with Calendar widget stores string representations. Date-based operators only work with ISO-formatted date fields. If your reports need date calculations, ensure you are using compatible component types.
Report state persists in local storage. Filter selections, column visibility, and sort order persist in the browser’s local storage. This improves user experience but means clearing the browser cache resets report preferences. For applications requiring server-side state persistence, you need custom implementation.
Enterprise license required. The Reporting Module is available only for self-hosted Enterprise deployments with the reporting feature enabled in the license. It is not available on the SaaS platform at portal.form.io.
Embedding Reports in Your Application
Reports are designed for embedding, not just viewing in the Developer Portal. The @formio/reporting npm package provides the renderer, and individual reports can be embedded by URL or JSON schema.
Installation adds the reporting module to your application:
npm install @formio/reporting
Connection requires a library license with reporting enabled:
javascript
import { Formio } from '@formio/js';
import reporting from '@formio/reporting';
Formio.license = 'yourLibraryLicenseKey';
Formio.use(reporting);
Embedding a report by URL:
Formio.Report.create(element, 'https://yourproject.form.io/report/employeereport')
.then(report => {
// Report instance available for event handling
});
The embedded report includes the full interactive interface: grid with sortable columns, pagination controls, filter inputs (if configured), column visibility toggles, and action buttons. Users interact with reports directly in your application without accessing the Form.io portal.
Report events allow custom logic in response to user actions. You can subscribe to rowClick, rowSelectChange, page, fetchDataErrors, and other events to trigger application-specific behavior when users interact with report data.
Permissions and Access Control
Reports inherit Form.io’s permission system through multiple layers.
Report access is controlled through the Reporting UI resource. Users need Read All Submission permission on the Reporting UI resource to view reports. This permission is typically granted to authenticated users with appropriate roles.
Report data access depends on permissions for each source form. A user viewing a report that joins Employee and Evaluation forms needs Read All Submission permission on both forms. If a user has access to the report but not to one of its source forms, the report will fail to load data.
Project-level access requires the user’s role to have Read All permission at the project level.
The permission model means report visibility and data access are controlled through the same roles and permissions system that governs forms. You do not create separate reporting-specific access controls.
When to Use Reports vs. External Analytics
The Reporting Module fits specific use cases well and fits others poorly.
Use the Reporting Module when:
You need to provide end users with interactive data views within your application. The embeddable reports deliver filtering, sorting, and export capabilities without building custom UI.
Your analysis requirements align with MongoDB aggregation operators. Date calculations, numeric aggregations, string manipulation, and group summaries are well-supported.
Data relationships map cleanly to form connections. Parent-child relationships, lookup references, and shared identifiers enable joins.
Report definitions are stable enough to configure through the wizard. Ad-hoc analysis with constantly changing requirements may find the configuration overhead limiting.
Use external analytics tools when:
You need visualization beyond tabular data. Charts, graphs, dashboards, and visual analytics require tools like Tableau, Power BI, or custom charting libraries fed by exported data.
Analysis spans multiple projects or external data sources. Cross-project reporting or joins with non-Form.io data require ETL pipelines and external analytics platforms.
You need real-time streaming analytics or complex statistical operations beyond MongoDB’s aggregation capabilities.
Your team prefers writing queries directly. Developers comfortable with MongoDB aggregation syntax may find the visual interface limiting compared to direct database access.
Direct Database Access for Advanced Users
Self-hosted Form.io deployments provide direct access to the MongoDB database. For analysis beyond the Reporting Module’s capabilities, you can query collections directly using MongoDB shell, Compass, or application code.
The submissions collection contains all form submission documents. Direct queries support the full MongoDB aggregation framework without the Reporting Module’s operator subset limitations. You can build complex pipelines, use operators not exposed in the UI, and export results in any format.
This path requires MongoDB expertise and careful attention to performance. Complex aggregations on large submission collections can be resource-intensive. Unlike the Reporting Module, direct queries have no built-in pagination or result caching.
For organizations with dedicated data engineering capabilities, direct database access combined with external analytics platforms often provides more sophisticated analysis than the Reporting Module alone. The module serves as the operational reporting layer for application users while data teams work with the underlying MongoDB data for deeper analysis.
Related Resources
- Reporting Module Documentation provides step-by-step configuration guidance
- Reporting Module Announcement explains the module’s capabilities
- MongoDB Aggregation Pipeline covers the underlying technology
- Export Form Data describes CSV and JSON export options for external analysis
- Why Form.io Requires MongoDB explains the database architecture
- Form Schemas vs Submissions clarifies the data model
- API Documentation covers submission endpoints for programmatic data access
- Teams and Permissions explains the access control model that governs reports
