Skip to main content

Form Reactions

Form Reactions enable real-time field updates by connecting form field events to workflows. When a user interacts with a field (blur, change, focus), a reaction can execute a workflow and automatically update other form fields with the results.

What Are Form Reactions?โ€‹

Form Reactions are a powerful feature that bridges forms and workflows, enabling dynamic, intelligent forms that respond to user input in real-time.

Example Use Cases:

  • Company Lookup: User enters a company domain โ†’ workflow fetches company data from an API โ†’ auto-fills company name, industry, and size fields
  • Address Validation: User enters a postal code โ†’ workflow validates and looks up location โ†’ auto-fills city and state
  • Price Calculation: User selects products โ†’ workflow calculates pricing โ†’ updates total price field
  • AI Categorization: User enters a description โ†’ AI classifies the content โ†’ suggests category and tags
  • Real-time Validation: User enters an email โ†’ workflow checks database โ†’ shows availability status

How Reactions Workโ€‹

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”         โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”         โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Form Field โ”‚ โ”‚ Workflow โ”‚ โ”‚ Form Fields โ”‚
โ”‚ Event โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ–บ โ”‚ Execution โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ–บ โ”‚ Updated โ”‚
โ”‚ (blur/change) โ”‚ โ”‚ โ”‚ โ”‚ โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

1. User interacts with a form field (e.g., leaves domain field)
2. Reaction detects the configured event (blur)
3. Workflow executes with form data as context
4. Workflow processes data (API calls, transforms, AI, etc.)
5. Form Field Update node returns field mappings
6. Form fields are automatically updated with new values

Creating a Form Reactionโ€‹

Step 1: Build the Reaction Workflowโ€‹

First, create a workflow with these key nodes:

  1. Field Event Trigger (entry point)

    • Receives the triggering field data and full form context
    • Configure trigger mode (any/all) and debounce
  2. Processing Nodes (your business logic)

    • HTTP Request to fetch external data
    • Transform to modify data structure
    • AI nodes for classification or extraction
    • MongoDB queries for database lookups
  3. Form Field Update (output)

    • Maps workflow data to form fields
    • Configures null value handling
    • Sets feedback mode (silent, subtle, toast)

Step 2: Configure the Reaction on Your Formโ€‹

Once your workflow is ready:

  1. Open your form in the Form Builder
  2. Navigate to the Reactions section
  3. Click "Add Reaction"
  4. Configure:
    • Name: Descriptive name (e.g., "Company Domain Lookup")
    • Workflow: Select your reaction workflow
    • Trigger Fields: Which fields trigger this reaction
    • Trigger Event: When to fire (blur, change, focus)
    • Debounce: Delay to prevent rapid firing (recommended: 500ms for text)

Workflow Nodes for Reactionsโ€‹

Field Event Triggerโ€‹

The entry point for all reaction workflows.

Configuration:

OptionDescription
Form IDUsually set automatically by the reaction system
Trigger Modeany fires on any field, all requires all fields to have values
Debounce (ms)Delay before executing (0-30000ms)

Output Data:

{
triggerField: "companyDomain", // Field that triggered
triggerEvent: "blur", // Event type
fieldValue: "mongodb.com", // Value of triggering field
formData: { // Complete form data
companyDomain: "mongodb.com",
companyName: "",
industry: ""
},
formId: "form_abc123",
reactionId: "reaction_xyz789"
}

Accessing Data in Downstream Nodes:

// Access the triggering field value
{{nodes.fieldEventTrigger.fieldValue}}

// Access a specific form field
{{nodes.fieldEventTrigger.formData.companyDomain}}

// Access the event type
{{nodes.fieldEventTrigger.triggerEvent}}

Form Field Updateโ€‹

Maps workflow outputs to form fields.

Configuration:

OptionDescription
Feedback ModeHow to notify users: silent, subtle, or toast
Validate After UpdateRun form validation after applying updates
Field MappingsArray of source โ†’ field mappings

Field Mapping Options:

OptionDescription
Form Field PathTarget field (e.g., companyName, address.city)
Source Data PathPath in workflow data (e.g., httpRequest.data.company.name)
Null Behaviorskip (default), clear, or default

Example Mappings:

Source: httpRequest.data.company.name     โ†’ Field: companyName
Source: httpRequest.data.company.industry โ†’ Field: industry
Source: httpRequest.data.company.size โ†’ Field: employeeCount

Output Data:

{
success: true,
updates: {
companyName: "MongoDB, Inc.",
industry: "Technology",
employeeCount: "5000+"
},
updatedFields: ["companyName", "industry", "employeeCount"],
skippedFields: []
}

Reaction Configurationโ€‹

Reaction Object Structureโ€‹

interface FormReaction {
id: string; // Unique identifier
name: string; // Display name
description?: string; // Optional description
workflowId: string; // ID of the workflow to execute

trigger: {
fields?: string[]; // Fields that trigger this reaction
event?: 'change' | 'blur' | 'focus' | 'validate' | 'clear';
debounceMs?: number; // Delay before executing (0-30000ms)
condition?: string; // Optional trigger condition
};

execution: {
mode: 'sync'; // Synchronous execution (v1)
timeoutMs?: number; // Max execution time (default: 10000ms)
};

feedback?: {
showLoading?: boolean; // Show loading indicator
loadingText?: string; // Custom loading message
showSuccess?: boolean; // Show success feedback
showError?: boolean; // Show error messages
};

enabled: boolean; // Whether reaction is active
}

Trigger Eventsโ€‹

EventWhen It FiresBest For
blurUser leaves the fieldDomain lookups, validation
changeValue changesCalculations, live updates
focusUser enters the fieldPre-loading data
validateField validation runsCustom validation
clearField is clearedResetting related fields

Debounce Settingsโ€‹

Field TypeRecommended Debounce
Text input500ms
Select/Dropdown0ms
Checkbox/Radio0ms
Search field300-500ms

API Referenceโ€‹

All endpoints require authentication and an orgId query parameter.

List Reactionsโ€‹

GET /api/forms/{formId}/reactions?orgId={orgId}

Response:

{
"success": true,
"reactions": [...],
"total": 3
}

Create Reactionโ€‹

POST /api/forms/{formId}/reactions?orgId={orgId}
Content-Type: application/json

{
"name": "Company Lookup",
"description": "Fetch company data on domain blur",
"workflowId": "wf_abc123",
"trigger": {
"fields": ["companyDomain"],
"event": "blur",
"debounceMs": 500
},
"execution": {
"mode": "sync",
"timeoutMs": 10000
},
"feedback": {
"showLoading": true,
"loadingText": "Looking up company..."
}
}

Get Reactionโ€‹

GET /api/forms/{formId}/reactions/{reactionId}?orgId={orgId}

Update Reactionโ€‹

PUT /api/forms/{formId}/reactions/{reactionId}?orgId={orgId}
Content-Type: application/json

{
"enabled": false,
"trigger": { "debounceMs": 1000 }
}

Delete Reactionโ€‹

DELETE /api/forms/{formId}/reactions/{reactionId}?orgId={orgId}

Execute Reactionโ€‹

POST /api/forms/{formId}/reactions/execute?orgId={orgId}
Content-Type: application/json

{
"reactionId": "reaction_abc123",
"triggerField": "companyDomain",
"triggerEvent": "blur",
"fieldValue": "mongodb.com",
"formData": {
"companyDomain": "mongodb.com",
"companyName": ""
}
}

Response:

{
"success": true,
"status": "completed",
"updates": {
"companyName": "MongoDB, Inc.",
"industry": "Technology"
},
"durationMs": 850
}

React Integrationโ€‹

useFormReactions Hookโ€‹

The useFormReactions hook provides React integration for form reactions.

import { useFormReactions } from '@/hooks/useFormReactions';

function MyForm({ formId, orgId, reactions }) {
const {
triggerReaction,
cancelReaction,
hasReaction,
getFieldReactions,
reactionStates,
pendingFields,
recentlyUpdatedFields,
} = useFormReactions({
formId,
orgId,
reactions,
onFieldUpdate: (fieldPath, value) => {
// Update your form state
setFormData(prev => ({ ...prev, [fieldPath]: value }));
},
onReactionStart: (reactionId) => {
console.log('Reaction started:', reactionId);
},
onReactionComplete: (reactionId, result) => {
console.log('Reaction completed:', result);
},
onReactionError: (reactionId, error) => {
console.error('Reaction failed:', error);
},
});

// Trigger a reaction on field blur
const handleFieldBlur = (fieldName: string, value: any) => {
triggerReaction(reactionId, {
triggerField: fieldName,
triggerEvent: 'blur',
fieldValue: value,
formData: currentFormData,
});
};

// Show loading state for a field
const isFieldLoading = pendingFields.has('companyName');

// Check if field was recently updated
const wasRecentlyUpdated = recentlyUpdatedFields.has('companyName');

return (
<form>
<input
name="companyDomain"
onBlur={(e) => handleFieldBlur('companyDomain', e.target.value)}
/>
<input
name="companyName"
disabled={isFieldLoading}
className={wasRecentlyUpdated ? 'highlight' : ''}
/>
</form>
);
}

Hook Return Valuesโ€‹

ValueTypeDescription
triggerReactionFunctionManually trigger a reaction
cancelReactionFunctionCancel a pending reaction
hasReactionFunctionCheck if field has reactions
getFieldReactionsFunctionGet all reactions for a field
reactionStatesMapCurrent state of each reaction
pendingFieldsSetFields with pending reactions
recentlyUpdatedFieldsSetFields recently updated

Reaction Statesโ€‹

interface ReactionState {
status: 'idle' | 'pending' | 'loading' | 'success' | 'error';
error?: string;
lastExecutedAt?: Date;
lastResult?: any;
}

Best Practicesโ€‹

1. Use Appropriate Debounceโ€‹

// Text fields - wait for user to finish typing
trigger: { debounceMs: 500 }

// Select fields - respond immediately
trigger: { debounceMs: 0 }

2. Handle Errors Gracefullyโ€‹

Configure feedback to show errors:

feedback: {
showError: true,
showLoading: true
}

3. Set Reasonable Timeoutsโ€‹

execution: {
timeoutMs: 10000 // 10 seconds is usually sufficient
}

4. Use Null Behavior Wiselyโ€‹

// Skip update if API returns null
{ nullBehavior: 'skip' }

// Clear field if source is empty
{ nullBehavior: 'clear' }

// Use default value
{ nullBehavior: 'default', defaultValue: 'Unknown' }

5. Keep Workflows Simpleโ€‹

  • Focus on single responsibility
  • Use transforms to shape data
  • Handle errors in the workflow

Limitationsโ€‹

Current Phase (v1)โ€‹

  • Synchronous execution only: Workflows run inline, not via job queue
  • Manual trigger: Auto-attachment to field events coming in Phase 3
  • Transform expressions: Accepted but not executed (requires sandboxing)
  • Cascade depth: Maximum of 3 to prevent infinite loops

Planned Featuresโ€‹

  • Async execution via job queue (Phase 5)
  • Automatic field event attachment (Phase 3)
  • Transform expression execution
  • Visual reaction builder in Form Builder

Troubleshootingโ€‹

Reaction Not Firingโ€‹

  1. Check that the reaction is enabled
  2. Verify the trigger field name matches exactly
  3. Ensure the workflow exists and is accessible
  4. Check debounce isn't too long

Field Updates Not Appearingโ€‹

  1. Verify the Form Field Update node mappings
  2. Check source paths match workflow output
  3. Ensure null behavior is configured correctly
  4. Look for errors in reaction execution

Timeout Errorsโ€‹

  1. Increase the execution timeout
  2. Optimize the workflow (fewer nodes, faster API calls)
  3. Check for slow external API responses

Cascade Loop Detectedโ€‹

  1. Ensure reactions don't update their own trigger fields
  2. Review all reactions that might create circular updates
  3. Simplify reaction chains

Next Stepsโ€‹