### Server-Side Error Logging Examples
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/errors.md
Examples of using `self.apos.util.error` and `self.apos.util.warn` for logging different types of errors and warnings on the server-side.
```javascript
self.apos.util.error('reCAPTCHA submission error', e);
self.apos.util.error('⚠️ @apostrophecms/form submission email notification error: ', err);
```
```javascript
self.apos.util.error(error);
```
```javascript
self.apos.util.warn(req.t('aposForm:fileMissingEarly', { path: file }));
```
--------------------------------
### Client-side Form Submission Example
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/form-module.md
Prepare and send form data from the client to the server for processing. Includes JSON data and file uploads.
```javascript
// Client-side form submission
const formElement = document.querySelector('form');
const formData = new FormData(formElement);
const jsonData = {
_id: formElement.dataset.formId,
fieldName: formElement.querySelector('input[name="fieldName"]').value,
// ... additional fields
};
formData.append('data', JSON.stringify(jsonData));
// Server-side (via API endpoint)
// POST /api/v1/@apostrophecms/form/submit
```
--------------------------------
### Submission Data with Captured Query Parameters
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/endpoints.md
Example of submission data including captured query parameters from the URL.
```javascript
{
_id: 'form-123',
email: 'user@example.com',
queryParams: {
source: 'email-campaign',
campaign: 'summer2024'
}
}
```
--------------------------------
### Radio Field Configuration Example
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/field-widgets.md
Shows the configuration for a radio button field, including its label, name, requirement status, and available choices.
```javascript
// Form field configuration
{
fieldLabel: 'How did you hear about us?',
fieldName: 'source',
required: true,
choices: [
{ label: 'Search Engine', value: 'search' },
{ label: 'Social Media', value: 'social' },
{ label: 'Word of Mouth', value: 'referral' }
]
}
// Output
{
source: 'search' // Single value
}
```
--------------------------------
### Email Condition Value Matching Examples
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/types.md
Illustrates how to specify single or multiple values for email condition matching, including handling values with commas.
```javascript
// Single value
value: "yes"
// Multiple values (OR logic)
value: "option1, option2, option3"
// Quoted values with commas
value: '"value, with, commas", "another, value"'
```
--------------------------------
### Form Query Parameter Setup
Source: https://github.com/apostrophecms/form/blob/main/modules/@apostrophecms/form-widget/views/widgetBase.html
This code block demonstrates how to construct a comma-separated string of query parameter keys if they are defined for the form. This is used for passing parameters to the form.
```html
{% if form %} {% set params = false %} {% if form.queryParamList %} {% set params = '' %} {% for param in form.queryParamList %} {% if loop.last %} {% set params = params + param.key %} {% else %} {% set params = params + param.key + ',' %} {% endif %} {% endfor %} {% endif %}
```
--------------------------------
### Form Widget Configuration Example
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/field-widgets.md
Demonstrates how to embed a form into a page or rich-text area using the form widget. It references a form document via a relationship.
```javascript
// Form widget configuration in a page/rich-text area
{
type: '@apostrophecms/form-widget',
_form: [
{
_id: 'form-document-id',
title: 'Contact Us'
}
]
}
```
--------------------------------
### Environment Variables for reCAPTCHA Keys
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/recaptcha.md
Example of how to export reCAPTCHA site and secret keys as environment variables. These are used in the module-level configuration.
```bash
export RECAPTCHA_SECRET_KEY='6Lc_...secret...'
export RECAPTCHA_SITE_KEY='6Lc_...site...'
```
--------------------------------
### Text Field Sanitization Example
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/field-widgets.md
Demonstrates the configuration and expected output for a text field widget, specifically an email input type, after sanitization.
```javascript
// Form field configuration
{
fieldLabel: 'Email Address',
fieldName: 'email',
inputType: 'email',
required: true,
placeholder: 'user@example.com'
}
// Submission data
{
email: 'user@example.com'
}
// Output after sanitization
{
email: 'user@example.com' // Laundered as string
}
```
--------------------------------
### Boolean Field Sanitization Example
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/field-widgets.md
Shows the configuration for a boolean field widget (e.g., a checkbox) and its expected sanitized output as a boolean value.
```javascript
// Form field configuration
{
fieldLabel: 'I agree to the terms',
fieldName: 'agreeToTerms',
required: true
}
// Output after sanitization
{
agreeToTerms: true // Laundered as boolean
}
```
--------------------------------
### Select Field Sanitization Example
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/field-widgets.md
Demonstrates how input values for a select field are sanitized against the provided choices. Invalid selections are filtered out.
```javascript
// Form field configuration
{
fieldLabel: 'Country',
fieldName: 'country',
required: true,
choices: [
{ label: 'United States', value: 'us' },
{ label: 'Canada', value: 'ca' },
{ label: 'Mexico', value: 'mx' }
]
}
// Output after sanitization
{
country: 'us' // Laundered against choices array
}
```
--------------------------------
### Configure Form Module with Environment Variables
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/configuration.md
Example of how to configure the '@apostrophecms/form' module in `app.js` using environment variables for reCAPTCHA keys and submission settings.
```javascript
const apos = require('apostrophe');
apos.launch({
shortName: 'my-site',
modules: {
'@apostrophecms/form': {
recaptchaSecret: process.env.RECAPTCHA_SECRET,
recaptchaSite: process.env.RECAPTCHA_SITE,
emailSubmissions: process.env.FORM_EMAIL !== 'false',
saveSubmissions: process.env.FORM_SAVE !== 'false'
}
}
});
```
--------------------------------
### Group Widget Configuration Example
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/field-widgets.md
Illustrates the configuration of a group widget, used to visually group related form fields under a common label. Nested groups are not permitted.
```javascript
// Group widget configuration
{
type: '@apostrophecms/form-group',
label: 'Contact Information',
contents: {
items: [
{
type: '@apostrophecms/form-text-field',
fieldLabel: 'Name',
fieldName: 'name'
},
{
type: '@apostrophecms/form-text-field',
fieldLabel: 'Email',
fieldName: 'email',
inputType: 'email'
}
]
}
}
```
--------------------------------
### Add Image Widget to Thank You Message
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/configuration.md
Example of how to add the image widget to the available widgets for the post-submission thank you message.
```javascript
{
thankYouWidgets: {
'@apostrophecms/rich-text': {
toolbar: ['styles', 'bold', 'italic', 'link']
},
'@apostrophecms/image': {}
}
}
```
--------------------------------
### Client-Side reCAPTCHA Implementation
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/recaptcha.md
This HTML and JavaScript example shows how to load the reCAPTCHA API, generate a token before form submission, and include it in the form data. It handles form submission using fetch API.
```html
```
--------------------------------
### Configure Form Module Options
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/configuration.md
Pass module options when configuring the form module in your project's `modules` configuration. This example shows common settings like reCAPTCHA keys and submission handling.
```javascript
// app.js or modules/@apostrophecms/form/index.js
module.exports = {
// ... module definition ...
options: {
recaptchaSecret: 'your-secret-key-here',
recaptchaSite: 'your-site-key-here',
emailSubmissions: true,
saveSubmissions: true,
classPrefix: 'my-form',
testing: false
}
}
```
--------------------------------
### Example of CSS Class Prefix Usage in Template
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/configuration.md
This HTML snippet demonstrates how the `classPrefix` option is used in a template to prepend a custom prefix to form element classes.
```html
```
--------------------------------
### Textarea Field Sanitization Example
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/field-widgets.md
Illustrates the configuration and sanitized output for a textarea field widget, suitable for longer text inputs. The input is laundered as a string.
```javascript
// Form field configuration
{
fieldLabel: 'Message',
fieldName: 'message',
required: true,
placeholder: 'Enter your message here...'
}
// Output after sanitization
{
message: 'User\'s multi-line message' // Laundered as string
}
```
--------------------------------
### Submission Data for Conditional Emails
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/endpoints.md
Example of submission data that would trigger conditional emails based on the 'requestType' field.
```javascript
{
_id: 'form-123',
requestType: 'Sales Inquiry',
message: 'I am interested in pricing'
}
```
--------------------------------
### Handling Missing reCAPTCHA Token
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/errors.md
This example shows how to ensure a reCAPTCHA token is generated and included in the submission data. It's crucial for forms with reCAPTCHA enabled to prevent 'recaptcha' errors.
```javascript
// Ensure reCAPTCHA token is generated before submission
const token = await grecaptcha.execute('site-key', { action: 'submit' });
if (!token) {
console.error('Failed to generate reCAPTCHA token');
return;
}
// Add token to submission data
submissionData.recaptcha = token;
```
--------------------------------
### Conditional Widget Configuration Example
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/field-widgets.md
Demonstrates how to configure a conditional widget to show or hide child fields based on another field's value. The 'state' field is only required if the 'country' field is 'us'.
```javascript
// Conditional widget configuration
{
type: '@apostrophecms/form-conditional',
conditionName: 'country',
conditionValue: 'us',
contents: {
items: [
{
type: '@apostrophecms/form-text-field',
fieldLabel: 'State',
fieldName: 'state',
required: true
}
]
}
}
// Submission logic
// If form input has country='us', the 'state' field is required
// If form input has country='ca', the 'state' field is skipped
```
--------------------------------
### Checkboxes Field Sanitization Example
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/field-widgets.md
Illustrates the sanitization process for a checkboxes field, which handles an array of selected values and ensures they are valid choices.
```javascript
// Form field configuration
{
fieldLabel: 'Interests',
fieldName: 'interests',
choices: [
{ label: 'Technology', value: 'tech' },
{ label: 'Sports', value: 'sports' },
{ label: 'Arts', value: 'arts' }
]
}
// Submission data
{
interests: ['tech', 'arts']
}
// Output after sanitization
{
interests: ['tech', 'arts'] // Array of valid choices
}
```
--------------------------------
### Database Indexes for Form Submissions
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/README.md
These are examples of database indexes used for efficient querying of form submissions. They allow for retrieval of submissions sorted by form ID and creation date, either chronologically or in reverse.
```javascript
{ formId: 1, createdAt: 1 }
```
```javascript
{ formId: 1, createdAt: -1 }
```
--------------------------------
### Throwing a Form Not Found Error
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/errors.md
Example of how to programmatically throw a 'notfound' error when a form submission is attempted for a non-existent form ID. This is checked early in the submission process.
```javascript
if (!form) {
throw self.apos.error('notfound');
}
```
--------------------------------
### ApostropheCMS Form Widget Base Template Logic
Source: https://github.com/apostrophecms/form/blob/main/modules/@apostrophecms/form-widget/views/widgetBase.html
This snippet shows the initial setup and variable declarations for the ApostropheCMS form widget's base template. It retrieves widget data, form details, and configuration for reCAPTCHA.
```html
{% set widget = data.widget %}
{% set form = data.widget._form[0] %}
{% set classPrefix = data.widget.classPrefix %}
{% set prependIfPrefix = apos.modules['@apostrophecms/form'].prependIfPrefix %}
{% set recaptchaSite = apos.modules['@apostrophecms/form'].options.recaptchaSite or (data.global.useRecaptcha and data.global.recaptchaSite) %}
{% set recaptchaReady = form.enableRecaptcha and recaptchaSite %}
```
--------------------------------
### Match File Names for Multiple Uploads
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/submission-handling.md
This method checks if a given string starts with a specified name and ends with a numerical pattern (e.g., '-1', '-2'). This is used to support multiple file uploads for a single form field.
```javascript
matchesName(str, name) {
return str.startsWith(name) && str.match(/.+-\d+$/);
}
```
--------------------------------
### Restrict Form Widgets
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/configuration.md
Configure the `formWidgets` option to replace the default set of field widgets. This example restricts the available fields to text, textarea, and a custom button widget.
```javascript
{
formWidgets: {
'@apostrophecms/form-text-field': {},
'@apostrophecms/form-textarea-field': {},
'@apostrophecms/form-button': {} // Custom widget
}
}
```
--------------------------------
### Clean reCAPTCHA Options
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/recaptcha.md
Validates reCAPTCHA configuration, ensuring both secret and site keys are present. If either is missing, both are removed to prevent partial setup.
```javascript
if (!options.recaptchaSecret || !options.recaptchaSite) {
delete options.recaptchaSite;
delete options.recaptchaSecret;
}
```
```javascript
// Configuration with both keys - valid
const opts1 = {
recaptchaSecret: 'secret-key',
recaptchaSite: 'site-key'
};
self.cleanOptions(opts1);
// Result: both keys remain
// Configuration with only secret - invalid
const opts2 = {
recaptchaSecret: 'secret-key'
};
self.cleanOptions(opts2);
// Result: recaptchaSecret is deleted, no reCAPTCHA
```
--------------------------------
### Get reCAPTCHA Secret Key
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/recaptcha.md
Retrieves the reCAPTCHA secret key, checking module options first and then global settings. Returns null if no configuration is found.
```javascript
const secret = await self.getRecaptchaSecret(req, self);
if (secret) {
// reCAPTCHA is enabled and configured
}
```
--------------------------------
### Get Choice Values from Widget
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/field-widgets.md
Extracts an array of choice values from a widget configuration, typically used for select-type fields. Returns an array of strings.
```javascript
const choices = self.getChoicesValues(selectWidget);
// Returns: ['option1', 'option2', 'option3']
```
--------------------------------
### Throwing Field Sanitization Errors
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/errors.md
This example demonstrates how to throw a custom 'invalid' error with specific field error data during form field sanitization on the server-side. This allows for detailed client-side error reporting.
```javascript
throw self.apos.error('invalid', {
fieldError: {
field: widget.fieldName,
error: string,
message: req.t('aposForm:...')
}
});
```
--------------------------------
### Extend Form Module with Custom Submission Handlers
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/submission-handling.md
This example shows how to extend the ApostropheCMS form module to add custom submission handlers like validation or webhook integration. Handlers are executed in registration order after built-in logic.
```javascript
module.exports = {
extend: '@apostrophecms/form',
handlers(self) {
return {
submission: {
async customValidator(req, form, data) {
// Custom validation logic
if (!isValid(data)) {
throw self.apos.error('invalid', {
fieldError: {
field: 'fieldName',
error: 'custom',
message: 'Custom error'
}
});
}
},
async sendWebhook(req, form, data) {
// Send submission to external webhook
await fetch('https://example.com/webhook', {
method: 'POST',
body: JSON.stringify(data)
});
}
}
};
}
};
```
--------------------------------
### Override Piece-Type Configuration
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/configuration.md
Extend the '@apostrophecms/form' module to override default piece-type options. This example enables SEO fields.
```javascript
module.exports = {
extend: '@apostrophecms/form',
options: {
seoFields: true // Override default
}
}
```
--------------------------------
### Module Configuration Options
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/form-module.md
Configure core module settings such as labels, submission handling, and reCAPTCHA keys.
```javascript
{
label: 'aposForm:form',
pluralLabel: 'aposForm:forms',
quickCreate: true,
seoFields: false,
openGraph: false,
i18n: {
ns: 'aposForm',
browser: true
},
shortcut: 'G,O'
}
```
--------------------------------
### Initialize Submissions Collection
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/form-module.md
Asynchronously initializes the 'aposFormSubmissions' collection and sets up database indexes for efficient querying.
```javascript
async ensureCollection()
```
--------------------------------
### Throwing a Field-Level Error
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/errors.md
Example of how to programmatically throw a field-level error within the form submission process. This is typically done when validation rules are not met.
```javascript
throw self.apos.error('invalid', {
fieldError: {
field: widget.fieldName,
error: 'required',
message: req.t('aposForm:requiredError')
}
});
```
--------------------------------
### Form Divider Widget Configuration
Source: https://github.com/apostrophecms/form/blob/main/modules/@apostrophecms/form-divider-widget/views/widget.html
Sets up the widget's class name, prioritizing widget-specific options over manager options.
```html
{% set prependIfPrefix = apos.modules['@apostrophecms/form'].prependIfPrefix %} {% set className = '' %} {% if data.options.className %} {% set className = data.options.className %} {% elif data.manager.options.className %} {% set className = data.manager.options.className %} {% endif %}
```
--------------------------------
### Get Widget Manager
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/form-module.md
Retrieves the widget manager for a given field widget type. This is used to access methods for sanitizing and validating field values.
```javascript
const manager = self.apos.area.getWidgetManager(widget.type);
```
--------------------------------
### Default thankYouWidgets Configuration
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/configuration.md
The default configuration for thankYouWidgets includes only the rich text editor.
```javascript
{
'@apostrophecms/rich-text': {
toolbar: [
'styles', 'bold', 'italic', 'link',
'orderedList', 'bulletList'
]
}
}
```
--------------------------------
### Custom Validator Error Throwing
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/errors.md
This example demonstrates how a downstream handler can throw a custom error during form submission processing. The error is caught and returned in the API response.
```javascript
handlers(self) {
return {
submission: {
async customValidator(req, form, data) {
if (!data.email || !data.email.includes('@')) {
throw self.apos.error('invalid', {
fieldError: {
field: 'email',
error: 'invalid',
message: 'Invalid email format'
}
});
}
}
}
};
}
```
--------------------------------
### Capture URL Parameters Configuration
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/README.md
Enable the capture of URL parameters for form submissions by setting 'enableQueryParams' to true and defining the parameters to capture in 'queryParamList'. Each parameter can have a key and an optional length limit.
```javascript
{
enableQueryParams: true,
queryParamList: [
{ key: 'source', lengthLimit: 50 },
{ key: 'campaign', lengthLimit: 100 }
]
}
```
--------------------------------
### Configure Email Submission Conditions
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/configuration.md
Set up complex field value matching for email submission rules using CSV parsing. Values can be quoted to include commas.
```javascript
{
email: 'specialist@example.com',
conditions: [
{
field: 'issueType',
value: '"Issue A", "Issue B", "Issue with comma, inside"'
}
]
}
```
--------------------------------
### Configure reCAPTCHA Site Key
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/configuration.md
Provide the client-side public key for Google reCAPTCHA v3. This module-level configuration takes precedence over global settings.
```javascript
{
recaptchaSite: 'your-site-key-from-google'
}
```
--------------------------------
### Custom Score-Based reCAPTCHA Validation
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/recaptcha.md
Example of a custom submission handler that implements score-based reCAPTCHA validation. It throws an 'invalid' error if the reCAPTCHA score is below 0.5, indicating suspected bot activity.
```javascript
handlers(self) {
return {
submission: {
async scoreBasedValidation(req, form, data) {
if (form.enableRecaptcha && data.recaptchaScore < 0.5) {
throw self.apos.error('invalid', {
fieldError: {
global: true,
error: 'recaptcha',
message: 'Suspected bot activity'
}
});
}
}
}
};
}
```
--------------------------------
### Form Module Options Configuration
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/types.md
The configuration object for the form module. Allows customization of labels, creation options, SEO and OpenGraph fields, email settings, reCAPTCHA keys, CSS prefixes, and widget configurations.
```javascript
{
label: string,
pluralLabel: string,
quickCreate: boolean,
seoFields: boolean,
openGraph: boolean,
i18n: { ns: string, browser: boolean },
shortcut: string,
emailSubmissions: boolean,
saveSubmissions: boolean,
recaptchaSecret: string,
recaptchaSite: string,
classPrefix: string,
formWidgets: object,
thankYouWidgets: object,
testing: boolean
}
```
--------------------------------
### insertFieldFiles(req, name, files)
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/form-module.md
Asynchronously processes and inserts uploaded files as attachments, matching them by field name. Returns an array of attachment IDs.
```APIDOC
## insertFieldFiles(req, name, files)
### Description
Process and insert uploaded files as attachments. Finds all uploaded files matching the field name, inserts each as an attachment, and returns an array of attachment IDs. Files are stored without permission restrictions.
### Parameters
#### Path Parameters
* None
#### Query Parameters
* None
#### Request Body
* None
### Method
* `async` Function
### Endpoint
* N/A
### Returns
* `Promise>` — Array of attachment IDs
```
--------------------------------
### Configure Query Parameter Validation
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/configuration.md
Enable query parameter capture and define an allowlist with optional length limits. Parameters are URL-decoded and truncated.
```javascript
{
enableQueryParams: true,
queryParamList: [
{ key: 'source', lengthLimit: 50 },
{ key: 'campaign', lengthLimit: 100 },
{ key: 'utm_source' } // No limit
]
}
```
--------------------------------
### Usage of Testing Mode in Tests
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/configuration.md
Demonstrates how to use the testing mode in your tests. The `sendEmailSubmissions` method will return an array of recipients instead of sending emails.
```javascript
const recipients = await self.sendEmailSubmissions(req, form, data);
// returns: ['admin@example.com', 'sales@example.com']
// instead of actually sending emails
```
--------------------------------
### JavaScript Fetch Request to Submit Form
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/endpoints.md
This snippet demonstrates how to construct and send a form submission using the Fetch API in JavaScript. It includes building FormData, adding reCAPTCHA tokens, query parameters, and file uploads.
```javascript
async function submitForm(formElement) {
const formData = new FormData();
// Build submission object
const submissionData = {
_id: formElement.dataset.formId,
fieldName: formElement.querySelector('input[name="fieldName"]').value
};
// Add reCAPTCHA token if needed
if (window.grecaptcha) {
submissionData.recaptcha = await grecaptcha.execute();
}
// Add query parameters if needed
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.has('source')) {
submissionData.queryParams = {
source: urlParams.get('source')
};
}
formData.append('data', JSON.stringify(submissionData));
// Add file inputs
const fileInputs = formElement.querySelectorAll('input[type="file"]');
for (const input of fileInputs) {
for (const file of input.files) {
formData.append(`${input.name}-${i++}`, file);
}
}
// Submit
const response = await fetch('/api/v1/@apostrophecms/form/submit', {
method: 'POST',
body: formData
});
const result = await response.json();
if (response.ok) {
console.log('Form submitted successfully');
} else {
console.log('Validation errors:', result.formErrors);
}
return result;
}
```
--------------------------------
### Query Parameter Configuration Structure
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/types.md
Defines how URL query parameters are captured and stored, including their name and an optional length limit.
```javascript
{
key: string,
lengthLimit: integer
}
```
--------------------------------
### Enable reCAPTCHA Configuration
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/README.md
Configure reCAPTCHA for your forms by providing the secret and site keys in the module configuration. This requires client-side integration as well.
```javascript
{
'@apostrophecms/form': {
recaptchaSecret: process.env.RECAPTCHA_SECRET,
recaptchaSite: process.env.RECAPTCHA_SITE
}
}
```
--------------------------------
### Query Parameter Capture Configuration
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/endpoints.md
Configure the form to capture specific URL query parameters. These parameters are then included in the submission data.
```javascript
{
title: 'Newsletter Signup',
enableQueryParams: true,
queryParamList: [
{ key: 'source', lengthLimit: 50 },
{ key: 'campaign', lengthLimit: 100 }
]
}
```
--------------------------------
### Configure Form Module with reCAPTCHA
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/README.md
Launch ApostropheCMS with the form module configured for reCAPTCHA, enabling email and database submissions.
```javascript
const apos = require('apostrophe');
apos.launch({
modules: {
'@apostrophecms/form': {
recaptchaSecret: 'your-secret-key',
recaptchaSite: 'your-site-key',
emailSubmissions: true,
saveSubmissions: true
}
}
});
```
--------------------------------
### ensureCollection()
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/form-module.md
Initialize the submissions collection and indexes. This asynchronous method creates the `aposFormSubmissions` collection and establishes necessary database indexes for efficient querying.
```APIDOC
## ensureCollection()
### Description
Initialize the submissions collection and indexes. This asynchronous method creates the `aposFormSubmissions` collection and establishes necessary database indexes for efficient querying.
### Signature
```javascript
async ensureCollection()
```
### Returns
`Promise`
```
--------------------------------
### File Handling Methods
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/README.md
Methods for processing file uploads within form submissions.
```APIDOC
### File Handling
- **`insertFieldFiles(req, name, files)`**
- Description: Process and insert uploaded files associated with a form field.
- **`normalizeFiles(req, res, next)`**
- Description: Express middleware to normalize file uploads before processing.
```
--------------------------------
### Insert Uploaded Files as Attachments
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/form-module.md
Asynchronously processes and inserts uploaded files matching a given field name as attachments. Returns an array of attachment IDs. Files are stored without permission restrictions.
```javascript
async insertFieldFiles(req, name, files)
```
--------------------------------
### File Processing
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/submission-handling.md
File fields are processed specially. Client-side, they are marked as 'files-pending'. The server then handles the insertion of these files, returning an array of their IDs.
```APIDOC
## File Processing
File fields are handled specially. On the client, the field value is set to `'files-pending'`. The server processes these:
### File Insertion
**Method:** `insertFieldFiles(req, name, files)`
Files are matched by name pattern and inserted without permission restrictions.
### File Name Matching
**Method:** `matchesName(str, name)`
Matches files named like `fieldName-1`, `fieldName-2`, etc., to support multiple file uploads per field.
```
--------------------------------
### Insert Field Files
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/submission-handling.md
This asynchronous method handles the insertion of uploaded files into the ApostropheCMS attachment storage. It iterates through provided files, matches them against a given field name pattern, inserts them as attachments, and returns an array of their IDs.
```javascript
async insertFieldFiles (req, name, files) {
const ids = [];
for (const entry in files) {
if (!self.matchesName(entry, name)) {
continue;
}
const attachment = await self.apos.attachment.insert(req, files[entry], {
permissions: false
});
ids.push(attachment._id);
}
return ids;
}
```
--------------------------------
### Discover Form Fields and Track Conditionals
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/submission-handling.md
Walks through the form's content areas to discover all fields and track conditional widgets. This allows for complex nested form structures while maintaining flat submission data.
```javascript
const areas = [];
const fieldNames = [];
const conditionals = {};
self.apos.area.walk({
contents: form.contents
}, function(area) {
areas.push(area);
});
for (const area of areas) {
const widgets = area.items || [];
for (const widget of widgets) {
fieldNames.push(widget.fieldName);
if (widget.type === '@apostrophecms/form-conditional') {
self.trackConditionals(conditionals, widget);
}
}
}
```
--------------------------------
### Send Email with Named Template
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/form-module.md
Sends an email using a specified template and configuration options. Useful for sending confirmation or notification emails. The 'from', 'to', 'subject', 'form', and 'data' can be customized.
```javascript
await self.sendEmail(req, 'emailConfirmation', {
form: formDocument,
data: submissionData,
from: 'noreply@example.com',
to: 'user@example.com',
subject: 'Thank you for your submission'
});
```
--------------------------------
### getRecaptchaSecret(req, self)
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/form-module.md
Asynchronously retrieves the reCAPTCHA secret key, checking module options first and then global settings. Returns null if the key is not configured in either location.
```APIDOC
## getRecaptchaSecret(req, self)
### Description
Retrieve reCAPTCHA secret key from options or global settings. Returns the reCAPTCHA secret from module options, falling back to global settings if available. Returns null if neither source has the key configured.
### Parameters
#### Path Parameters
* None
#### Query Parameters
* None
#### Request Body
* None
### Method
* `async` Function
### Endpoint
* N/A
### Returns
* `Promise` — Secret key or null if not configured
```
--------------------------------
### Not Found Response
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/endpoints.md
Returned with a 404 status if the form ID specified in the submission request does not exist.
```json
{
"error": "notfound"
}
```
--------------------------------
### Conditional Logic Methods
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/README.md
Methods for managing conditional visibility of form fields.
```APIDOC
### Conditionals
- **`trackConditionals(conditionals, widget)`**
- Description: Map field visibility rules based on conditional settings.
- **`collectToSkip(input, conditionals, skipFields)`**
- Description: Identify fields that should be skipped based on conditional logic.
```
--------------------------------
### Client-Side Fetch and Error Handling
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/errors.md
This client-side code demonstrates how to fetch form submission results and handle potential errors returned in the response, including 'notfound' and 'invalid' error types.
```javascript
const response = await fetch('/api/v1/@apostrophecms/form/submit', {
method: 'POST',
body: formData
});
const result = await response.json();
if (!response.ok) {
// Handle errors
if (result.error === 'notfound') {
// Form not found
} else if (result.error === 'invalid') {
// Process formErrors array
result.formErrors.forEach(err => {
if (err.global) {
// Global error
} else {
// Field-level error
}
});
}
}
```
--------------------------------
### Check Input Macro
Source: https://github.com/apostrophecms/form/blob/main/modules/@apostrophecms/form-base-field-widget/views/fragments/utility.html
A placeholder macro for checking input related to form fields. It retrieves a prefixer function from the form module's options.
```html
{% macro checkInput(widget, choice, id) %} {% set prefixer = apos.modules\[\'@apostrophecms/form\'\]\.prependIfPrefix %} {% endmacro %}
```
--------------------------------
### Handling reCAPTCHA Configuration Errors
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/errors.md
This snippet illustrates how to detect and handle reCAPTCHA configuration errors on the client-side. It suggests showing a user-friendly message indicating temporary unavailability.
```javascript
if (response.error === 'recaptcha' &&
response.formErrors[0].message.includes('configuration')) {
console.error('Server reCAPTCHA configuration issue');
// Show user-friendly message
showError('Form submission is temporarily unavailable');
}
```
--------------------------------
### Success Response
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/endpoints.md
An empty object is returned on successful form submission, indicating the data was processed without errors.
```json
{}
```
--------------------------------
### Register Submission Event Handler
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/submission-handling.md
This demonstrates how to register a custom handler for the 'submission' event. The handler receives the request, form, and submission data, enabling custom processing logic after a successful form submission.
```javascript
handlers(self) {
return {
submission: {
async myCustomHandler(req, form, data) {
// Process submission data
}
}
};
}
```
--------------------------------
### getRecaptchaSecret
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/recaptcha.md
Retrieves the reCAPTCHA secret key, checking module options first and then global settings. Returns the secret key as a string or null if not configured.
```APIDOC
## getRecaptchaSecret(req, self)
### Description
Retrieve the reCAPTCHA secret key from module configuration or global settings.
### Method Signature
```javascript
async getRecaptchaSecret(req, self)
```
### Parameters
#### Parameters
- **req** (Express.Request) - Request object for context
- **self** (object) - Module context (the form module instance)
### Returns
`Promise` — Secret key if configured, null otherwise
### Description
Resolves reCAPTCHA configuration in priority order:
1. Returns `self.options.recaptchaSecret` if set in module options
2. Falls back to `globalDoc.recaptchaSecret` if global settings enabled
3. Returns null if no configuration found
### Example
```javascript
const secret = await self.getRecaptchaSecret(req, self);
if (secret) {
// reCAPTCHA is enabled and configured
}
```
```
--------------------------------
### Configure reCAPTCHA Secret Key
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/configuration.md
Provide the server-side secret key for Google reCAPTCHA v3 verification. This module-level configuration takes precedence over global settings.
```javascript
{
recaptchaSecret: 'your-secret-key-from-google'
}
```
--------------------------------
### reCAPTCHA Configuration Error Response
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/endpoints.md
Illustrates error responses when reCAPTCHA is enabled but a server-side configuration issue prevents validation.
```json
{
"error": "invalid",
"formErrors": [
{
"global": true,
"error": "recaptcha",
"message": "reCAPTCHA configuration error"
}
]
}
```
--------------------------------
### Email Sending Options Object
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/configuration.md
The options object for the `sendEmail` method includes details about the form, submission data, sender, recipient, and subject.
```javascript
{
form: formDocument,
data: submissionData,
from: 'sender@example.com', // Optional; defaults to form.email
to: 'recipient@example.com', // Required
subject: 'Email Subject' // Optional; defaults to form.title
}
```
--------------------------------
### Configure Localization Namespace
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/configuration.md
Set the localization namespace to 'aposForm' for all localized strings used by the form module. This enables browser-side localization.
```javascript
{
i18n: {
ns: 'aposForm',
browser: true
}
}
```
--------------------------------
### Global Error Response Format (Form Not Found)
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/errors.md
Standardized format for reporting a global submission error when the specified form cannot be found. This error typically results in a 404 HTTP status.
```javascript
{
error: "notfound"
}
```
--------------------------------
### File Object Format
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/form-module.md
Defines the structure of a file object after normalization by `normalizeFiles`.
```javascript
{
path: string, // Temporary file path
name: string, // Original filename
type: string, // MIME type
size: number // File size in bytes
}
```
--------------------------------
### POST /api/v1/@apostrophecms/form/submit
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/form-module.md
Submit form data for processing and storage. This endpoint accepts multipart/form-data, parses it, and then processes the submission using the 'submitForm' middleware.
```APIDOC
## POST /api/v1/@apostrophecms/form/submit
### Description
Submit form data for processing and storage. This endpoint accepts multipart/form-data, parses it, and then processes the submission using the 'submitForm' middleware.
### Method
POST
### Endpoint
/api/v1/@apostrophecms/form/submit
### Parameters
#### Request Body
- **data** (string) - Required - JSON stringified form data object.
### Request Example
```json
{
"data": "{\"_id\": \"formId\", \"fieldName\": \"fieldValue\", \"recaptcha\": \"token\", \"queryParams\": {}}"
}
```
### Response
#### Success Response (200)
An empty object `{}` is returned upon successful submission.
#### Error Response Format
```json
{
"error": "string",
"formErrors": [
{
"field": "string",
"error": "string",
"message": "string"
}
]
}
```
- Status 400: `{ error: "invalid", formErrors: [] }`
- Status 404: `{ error: "notfound" }`
```
--------------------------------
### Database Index for Submissions (Ascending)
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/form-module.md
Defines the first database index on the 'aposFormSubmissions' collection, enabling efficient querying of submissions ordered by form ID and then creation date in ascending order.
```javascript
{ formId: 1, createdAt: 1 }
```
--------------------------------
### Divider Widget Configuration
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/field-widgets.md
Shows the default configuration for the divider widget, which is used for visual separation in forms. This widget does not affect form data.
```javascript
{
label: 'aposForm:divider',
initialModal: false,
className: 'apos-form-divider',
icon: 'minus-icon'
}
```
--------------------------------
### Field Widget Structure
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/types.md
Extends the base widget structure with properties specific to form input fields.
```javascript
{
type: '@apostrophecms/form-*-field-widget',
_id: string,
fieldName: string,
fieldLabel: string,
required: boolean,
classPrefix: string,
// Type-specific fields:
inputType: string, // Text field
placeholder: string, // Text/textarea/select fields
choices: array, // Select/radio/checkboxes fields
allowMultiple: boolean, // Select/file fields
size: integer, // Select field
checked: boolean, // Boolean field
limitSize: boolean, // File field
maxSize: integer // File field
}
```
--------------------------------
### Query Parameters Object Schema
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/endpoints.md
Defines the structure for the optional query parameters object, where each parameter is captured as a string value.
```javascript
{
paramKey: string,
}
```
--------------------------------
### checkRecaptcha(req, input, formErrors)
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/form-module.md
Asynchronously validates the reCAPTCHA token submitted with the form by calling Google's verification endpoint. Errors are appended to the `formErrors` array if validation fails or is not configured.
```APIDOC
## checkRecaptcha(req, input, formErrors)
### Description
Validate reCAPTCHA token submitted with the form. Validates the reCAPTCHA token by calling Google's verification endpoint. If validation fails or is not configured, appends an error object to formErrors. Does not throw; errors are collected for return to client.
### Parameters
#### Path Parameters
* None
#### Query Parameters
* None
#### Request Body
* None
### Method
* `async` Function
### Endpoint
* N/A
### Returns
* `Promise` — Modifies formErrors array in place
### Appended Error Object (if validation fails)
```javascript
{
global: true,
error: 'recaptcha',
message: string // Localized error message
}
```
```
--------------------------------
### cleanOptions
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/recaptcha.md
Validates and cleans reCAPTCHA configuration options, ensuring both secret and site keys are present. Modifies the options object in place.
```APIDOC
## cleanOptions(options)
### Description
Validate and clean reCAPTCHA configuration options.
### Method Signature
```javascript
cleanOptions(options)
```
### Parameters
#### Parameters
- **options** (object) - Module options object
### Returns
`undefined` — Modifies options object in place
### Description
Ensures that reCAPTCHA is only enabled if both the secret key and site key are provided. If either is missing, both are deleted to prevent partial configuration.
### Logic
```javascript
if (!options.recaptchaSecret || !options.recaptchaSite) {
delete options.recaptchaSite;
delete options.recaptchaSecret;
}
```
### Called
During module initialization in `init()` hook
### Example
```javascript
// Configuration with both keys - valid
const opts1 = {
recaptchaSecret: 'secret-key',
recaptchaSite: 'site-key'
};
self.cleanOptions(opts1);
// Result: both keys remain
// Configuration with only secret - invalid
const opts2 = {
recaptchaSecret: 'secret-key'
};
self.cleanOptions(opts2);
// Result: recaptchaSecret is deleted, no reCAPTCHA
```
```
--------------------------------
### Conditional Global Settings Logic
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/recaptcha.md
This JavaScript snippet demonstrates the condition under which reCAPTCHA configuration fields are added to the global document. It checks if module-level configuration is absent.
```javascript
if (!formOptions.recaptchaSecret && !formOptions.recaptchaSite) {
// Form module doesn't have module-level reCAPTCHA config
// Add global settings fields
}
```
--------------------------------
### reCAPTCHA Submission Error Response
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/endpoints.md
Illustrates error responses when reCAPTCHA is enabled but no token is provided during submission.
```json
{
"error": "invalid",
"formErrors": [
{
"global": true,
"error": "recaptcha",
"message": "reCAPTCHA submission error"
}
]
}
```
--------------------------------
### Retrieve Form Document by ID
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/submission-handling.md
Retrieves the form document from the database using its ID. Throws a 'notfound' error if the form does not exist. Handles page context and locale resolution.
```javascript
const formId = self.inferIdLocaleAndMode(req, input._id);
const form = await self.find(req, {
_id: self.apos.launder.id(formId)
}).toObject();
if (!form) {
throw self.apos.error('notfound');
}
```
--------------------------------
### Container Widget Structure
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/types.md
Defines the structure for container widgets like conditional fields or groups, extending the base widget properties.
```javascript
{
type: '@apostrophecms/form-conditional-widget' | '@apostrophecms/form-group-widget',
_id: string,
label: string, // Group widget
conditionName: string, // Conditional widget
conditionValue: string, // Conditional widget
contents: area
}
```
--------------------------------
### trackConditionals(conditionals, widget)
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/form-module.md
Tracks field visibility dependencies for conditional widgets by populating a conditionals object with field visibility rules. Maps condition names and values to arrays of field names that should be visible when that condition is met.
```APIDOC
## trackConditionals(conditionals, widget)
### Description
Track field visibility dependencies for conditional widgets. Populates the conditionals object with field visibility rules. Maps condition names and values to arrays of field names that should be visible when that condition is met.
### Parameters
#### Path Parameters
* None
#### Query Parameters
* None
#### Request Body
* None
### Method
* Function
### Endpoint
* N/A
### Returns
* `undefined` — Modifies conditionals object in place
### Conditionals Structure
```javascript
{
fieldName: {
value1: ['field1', 'field2'],
value2: ['field3', 'field4']
}
}
```
```
--------------------------------
### Form Document Schema
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/types.md
Defines the structure of a form piece document, including its fields and submission handling configuration.
```javascript
{
_id: ObjectId,
type: '@apostrophecms/form',
slug: string,
title: string,
contents: area,
submitLabel: string,
thankYouHeading: string,
thankYouBody: area,
sendConfirmationEmail: boolean,
emailConfirmationField: string,
enableRecaptcha: boolean,
enableQueryParams: boolean,
queryParamList: array,
emails: array,
email: string,
createdAt: Date,
updatedAt: Date,
// ... additional piece-type fields
}
```
--------------------------------
### Extract and Tidy Query Parameters
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/submission-handling.md
This method extracts specified query parameters from the input, validates them against an allowlist, skips parameters that match existing form field names, cleans them using `tidyParamValue`, and adds them to the output object.
```javascript
processQueryParams(form, input, output, fieldNames) {
if (!input.queryParams ||
(typeof input.queryParams !== 'object')) {
output.queryParams = null;
return;
}
if (Array.isArray(form.queryParamList) && form.queryParamList.length > 0) {
form.queryParamList.forEach(param => {
if (fieldNames.includes(param.key)) {
return; // Skip if matches existing field
}
const value = input.queryParams[param.key];
if (value) {
output[param.key] = self.tidyParamValue(param, value);
} else {
output[param.key] = null;
}
});
}
}
```
--------------------------------
### collectToSkip(input, conditionals, skipFields)
Source: https://github.com/apostrophecms/form/blob/main/_autodocs/api-reference/form-module.md
Determine which fields should be excluded from processing based on unmet conditions. This method iterates through conditionals and adds fields to `skipFields` if their visibility conditions are not met.
```APIDOC
## collectToSkip(input, conditionals, skipFields)
### Description
Determine which fields should be excluded from processing based on unmet conditions. This method iterates through conditionals and adds fields to `skipFields` if their visibility conditions are not met.
### Signature
```javascript
collectToSkip(input, conditionals, skipFields)
```
### Parameters
#### Path Parameters
- **input** (object) - Required - Form submission data.
- **conditionals** (object) - Required - Conditional field tracking object.
- **skipFields** (array) - Required - Array to append field names to.
### Returns
`undefined` — Modifies skipFields array in place.
```