Portal Community

Complete Interface

interface FormActionContext {
  // ── Identity ──────────────────────────────────────────────
  formId: string;              // Numeric form ID as string (e.g., "13001")
  tenantId: string;            // Current tenant ID
  userId?: string;             // Current user ID (if available from auth context)

  // ── Form Data ─────────────────────────────────────────────
  formValues: Record<string, any>;  // Snapshot of ALL current field values
  formEngine: FormEngine;            // Direct FormEngine access (advanced)

  // ── Services ─────────────────────────────────────────────
  apiClient: FormDefinitionApiClient; // Atlas Forms API (list/get/create/update forms)

  // ── Navigation ────────────────────────────────────────────
  navigate: (url: string, options?: { target?: '_self' | '_blank' }) => void;

  // ── Completion Signals ────────────────────────────────────
  complete: (message?: string) => void;   // Signal success
  fail: (reason?: string) => void;        // Signal failure (shows error)

  // ── Validation ────────────────────────────────────────────
  validate: () => Promise<boolean>;       // Run full form validation

  // ── Action Configuration ──────────────────────────────────
  config?: Record<string, any>;  // handlerConfig from the form schema action
}

Field-by-Field Reference

formValues

A plain object snapshot of all current field values at the moment the action was triggered. Keys are field IDs, values are the current field values. For data-table controls, the value is an array of row objects.

// Example formValues object
{
  "company-name": "Acme Corp",
  "contact-email": "jane@acme.com",
  "invoice-lines": [
    { "description": "Setup fee", "qty": 1, "price": 500 },
    { "description": "Monthly licence", "qty": 12, "price": 99 }
  ],
  "terms-accepted": true
}

formEngine

Direct access to the FormEngine instance. Use this for advanced scenarios: reading error state, programmatically setting field values, or triggering validation for specific fields only.

// Set a field value from within the handler
ctx.formEngine.setFieldValue('status', 'approved');

// Check if a specific field is valid
const emailErrors = ctx.formEngine.getFieldError('contact-email');
if (emailErrors) {
  ctx.fail('Please fix the email address first.');
  return;
}

apiClient

The same FormDefinitionApiClient instance used by the rest of the application. Useful for loading related forms, checking form metadata, or updating form records during the action.

complete() and fail()

These are the ONLY way to signal the end of your handler. Both exit the loading state on the button.

config

The handlerConfig object from the action schema. Use this to parameterise your handler so the same code can serve multiple use cases:

// Schema
{
  "type": "custom",
  "config": {
    "handlerType": "send-notification",
    "handlerConfig": {
      "channel": "slack",
      "recipient": "#approvals",
      "urgency": "high"
    }
  }
}

// Handler
const handler = async (ctx: FormActionContext) => {
  const { channel, recipient, urgency } = ctx.config ?? {};
  await notifyService.send({ channel, recipient, urgency, data: ctx.formValues });
  ctx.complete('Notification sent');
};