Skip to main content
Formulas enable automatic calculation of field values based on expressions that reference other fields. When a user changes a field value, all dependent formulas are automatically recalculated in the correct order, keeping your forms dynamic and always up-to-date.

Overview

Formulas allow you to create calculated fields that automatically update based on other field values. The formula system handles dependency resolution automatically, ensuring formulas are evaluated in the correct order even when fields depend on each other. Key Features:
  • Automatic dependency resolution
  • Circular dependency detection
  • Support for arithmetic, functions, and array operations
  • Real-time recalculation when field values change
  • Type-safe comparisons (no automatic type coercion)

Enabling Formulas

Formulas are automatically resolved by the JoyDoc component when enabled in the features prop:

How Formulas Work

Formulas consist of two parts:
  1. Formula Definition - The calculation expression stored in doc.formulas
  2. Formula Application - The link between a field and a formula stored in field.formulas
When a field value changes:
  1. JoyDoc automatically identifies all formulas that reference that field
  2. Determines the correct evaluation order (handles dependencies automatically)
  3. Evaluates all dependent formulas
  4. Updates field values with calculated results
  5. Calls onChange with the updated document

Formula Structure

Document-Level Formula Definitions

Define formulas at the document level in a formulas array:

Field-Level Formula Applications

Fields that should receive formula results have a formulas property:

Field References

Formulas reference fields by their _id property. You can reference any field in the document:

Basic Arithmetic

Formulas support standard arithmetic operations:
Note: Formulas can contain literal values ("5 + 3"), field references (field1 + field2), or a mix of both (field1 + 5).

Built-in Functions

The formula engine includes 50+ built-in functions across multiple categories.

Math Functions

String Functions

Array Functions

Array functions work with table fields and other array values:

Logic Functions

Date Functions

Important: Date functions preserve null values. If a date field is null/empty, date functions return null rather than treating it as the current date.

Arrow Functions (Lambda Functions)

Formulas support arrow functions for array operations. You can use either Notion-style (->) or JavaScript (=>) syntax:

Working with Table Fields

When working with table fields in lambda functions, access columns directly by their column field ID:

Comparison Operators

All comparison operators use strict type checking (no automatic type coercion):

Equality (==)

Type and value must be exactly the same:

Inequality (!=)

Returns true if types or values differ:

Greater Than (>)

Only works with numbers:

Less Than (<)

Only works with numbers:

Greater/Less Than or Equal (>=, <=)

Work like > and < but include equality:

Complete Examples

Example 1: Basic Calculation

Example 2: Conditional Logic

Example 3: Table Operations

Table Access:
  • table1[0] - Access first row (zero-indexed)
  • table1[0].columnName - Access specific column in first row
  • In lambda functions: (row) => row.columnName - Access column by field ID

Example 4: String Operations

Example 5: Date Operations

Example 6: Complex Table Operations

Dependency Resolution

Formulas automatically resolve dependencies and evaluate in the correct order:
The system automatically detects that multiplySum depends on sum, so it evaluates addAB first, then multiplySum.

Field Types and Formulas

Supported Field Types

Formulas can write calculated values to:
  • text - String results
  • textarea - String results
  • number - Numeric results
  • dropdown - String results
  • multiSelect - Array results
  • date - Timestamp results
  • chart - Array of chart line objects

Read-Only Field Types

These field types do NOT support formula writes:
  • signature
  • image
  • file
  • table
  • collection
Note: While table and collection fields cannot receive formula results, you can read their values in formulas (e.g., sum(map(table1, (row) => row.price))).

Common Patterns

Pattern 1: Calculate Total from Table

Pattern 2: Conditional Calculation

Pattern 3: Filter and Count

Pattern 4: Average with Filter

Pattern 5: String Concatenation

Pattern 6: Multiple Conditions

Integration with Conditional Logic

Formulas and conditional logic work independently:
  • Formulas - Calculate field values automatically
  • Conditional Logic - Control field/page visibility
A field can have both formulas and conditional logic:

Error Handling

Formulas are evaluated automatically by JoyDoc. If a formula has errors:
  1. The formula is skipped (doesn’t crash the form)
  2. Other formulas continue to evaluate
  3. The field retains its previous value
Common Errors:
  • Unknown Function - Function name typo (e.g., lenght instead of length)
  • Undefined Variable - Variable name doesn’t match lambda parameter
  • Circular Dependency - Fields reference each other in a loop
  • Type Mismatch - Formula result type doesn’t match field type

Best Practices

  1. Use Descriptive Formula IDs - Make formula IDs meaningful (calculateTotal vs f1)
  2. Add Descriptions - Use the desc field to document what each formula does
  3. Handle Null Values - Use empty() or null checks for optional fields
  4. Test Edge Cases - Test with empty arrays, null values, and zero values
  5. Keep Expressions Readable - Break complex formulas into multiple steps when possible
  6. Use Arrow Functions - Use => or -> syntax for cleaner array operations
  7. Validate Field Types - Ensure formula results match target field types
  8. Reference Existing Fields - Ensure referenced fields exist before using them

Troubleshooting

Formula Not Updating

  1. Check Formula Feature - Ensure features.formulas: true is set
  2. Check Formula Application - Ensure field has formulas array with correct formula reference
  3. Verify Field References - Ensure field IDs in expression match actual field IDs
  4. Check Field Type - Ensure field type supports formula writes

Formula Errors

  1. Unknown Function - Check function name spelling
  2. Undefined Variable - Verify variable names match lambda parameters
  3. Type Mismatch - Ensure formula result type matches field type
  4. Circular Dependency - Check for circular references between formulas

Debugging Tips

  1. Start Simple - Test with basic arithmetic first
  2. Check onChange - Verify onChange is being called with updated values
  3. Validate Document Structure - Ensure formulas array exists and is properly formatted
  4. Test Individual Formulas - Isolate formulas to identify issues

Complete Integration Example

In this example:
  • When unit_price or quantity changes, subtotal is automatically recalculated
  • When subtotal or discount_percent changes, discount_amount is recalculated
  • When subtotal or discount_amount changes, total is recalculated
  • All calculations happen automatically in the correct order