Portal Community

The Registration API

import { registerFormAction } from '@atlas-forms/control-registry-js';

// Register a handler
registerFormAction(
  'my-org:send-email',   // Type key (namespace:name recommended)
  myEmailHandler          // The FormActionHandler function
);

Naming Convention — Namespace Your Types

Built-in action types use simple names (submit, cancel). Custom action types should use a namespace prefix to avoid collisions with built-ins and other libraries:

PatternExampleUse For
orgname:actionbizfirst:approve-workflowInternal company actions
product:actionguardrails:activate-policyProduct-specific actions
@package/action@myorg/crm:link-accountPublished library actions

When to Register

Registration must happen before any form component renders. The correct place is application startup — typically main.tsx or the file imported first:

// main.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { AtlasFormsClient } from '@atlas-forms/client-js';
import { registerMyActions } from '@myorg/my-action-library';

// 1. Initialise client
AtlasFormsClient.getInstance({ apiBaseUrl: '...' });

// 2. Register action libraries BEFORE rendering
registerMyActions();
registerOtherActions();

// 3. Now render the app
ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode><App /></React.StrictMode>
);

Verifying Registration

import { getControlRegistry } from '@atlas-forms/control-registry-js';

const registry = getControlRegistry();

// Check if an action type is registered
const isRegistered = registry.hasAction('my-org:send-email');
console.log(isRegistered); // true

// List all registered action types
const allActions = registry.getActionTypes();
console.log(allActions); // ['submit', 'cancel', ..., 'my-org:send-email']

Overriding Built-In Actions

You can override a built-in action type by registering a handler with the same key. Use this sparingly — built-in overrides affect all forms in the application:

// Override the submit action globally
registerFormAction('submit', async (ctx) => {
  // Custom pre-submit logic (e.g., analytics event)
  analytics.track('form_submitted', { formId: ctx.formId });
  // Still validate and call onSubmit
  await ctx.validate();
  ctx.complete();
});
// Warning: this replaces the built-in submit behavior entirely
Collision Handling If you register the same type key twice, the second registration wins silently. Always use namespaced keys and never register the same key from two different libraries.