Portal Community

Schema Field

// Form schema JSON — the only change needed to switch players
{
  "metadata": {
    "formId":        42001,
    "title":         "New Employee Onboarding",
    "playerOverride": "card-section"   // <-- registered player ID
  },
  "sections": [ ... ],
  "controls": [ ... ]
}

FormMetadata Type

// packages/types-js/src/FormMetadata.ts

interface FormMetadata {
  formId:          number;
  title:           string;
  description?:    string;
  version?:        string;

  /** ID of a registered player to use instead of the default layout */
  playerOverride?: string;

  /** Additional arbitrary metadata passed through to the player */
  [key: string]: any;
}

Resolution Priority

When a form is rendered, the player is resolved in the following order:

PrioritySourceHow
1 (highest)Explicit prop<FormRenderer player="wizard" />
2Schema overridemetadata.playerOverride: "card-section"
3 (lowest)DefaultBuilt-in DefaultFormLayout

Passing an explicit player prop to FormRenderer always wins, regardless of what the schema specifies. This lets host applications force a particular player for all forms without modifying schemas.

Setting the Override in Atlas Forms Studio

In Studio, open Form Settings → Player. The dropdown lists all registered players by their label. Selecting one writes metadata.playerOverride into the saved schema automatically.

Passing Player-Specific Config

Custom players can read extra metadata fields to configure themselves. The entire metadata object is passed through schema.metadata, which the player component receives via its schema prop:

// Schema JSON — extra config fields under metadata
{
  "metadata": {
    "formId":        42001,
    "playerOverride": "wizard",
    "wizard": {
      "showProgressBar": true,
      "allowBackNavigation": false,
      "completionRedirectUrl": "/dashboard"
    }
  }
}

// WizardPlayer.tsx — reading the config
export const WizardPlayer: React.FC<FormPlayerProps> = ({ schema, initialValues = {}, onSubmit }) => {
  const config = (schema.metadata as any).wizard ?? {};
  const showProgress       = config.showProgressBar       ?? true;
  const allowBack          = config.allowBackNavigation   ?? true;
  const completionRedirect = config.completionRedirectUrl ?? '/';

  // ... rest of the player implementation
};

Tenant-Level Override

Tenant overrides (see Guide 15) can set playerOverride at the tenant level, replacing the base schema's player choice for a specific tenant without touching the base schema:

// Tenant override document
{
  "formGroupOverride": {
    "baseCategoryId": 420,
    "tenantId": 9001,
    "overrides": [
      {
        "formId": 42001,
        "path":   "metadata.playerOverride",
        "value":  "gov-accessible"
      }
    ]
  }
}
Unregistered Override Gracefully Falls Back If metadata.playerOverride references an ID that is not in the registry, FormRenderer logs a console.warn and renders the default player. It does not throw. This means a missing registration causes a silent visual regression rather than a crash — always verify registrations in your QA environment.

Schema Override vs Prop Override — Choosing the Right Approach

ScenarioRecommended Approach
One specific form always uses a custom layoutSchema metadata.playerOverride
All forms in a page/route use the same playerplayer prop on FormRenderer
Tenant A needs a different layout for a shared formTenant override setting metadata.playerOverride
A/B testing two layoutsplayer prop driven by feature flag
Runtime user preferenceplayer prop driven by state