Portal Community

Props Contract

interface ViewComponentProps {
  control: FormControl;    // Control config from schema (access settings via control.settings)
  value: any;              // The stored value to display
  mode: FormOperatingMode; // Always 'view' when ViewComponent is used
}

When to Provide a ViewComponent

Provide a dedicated ViewComponent when:

Skip ViewComponent for simple controls where the edit component already renders acceptably with readOnly prop.

Phone View Example

import React from 'react';
import type { ViewComponentProps } from '@atlas-forms/types-js';
import { formatPhoneNumber } from '../utils/phoneFormatter';

export const PhoneViewComponent: React.FC<ViewComponentProps> = ({ control, value }) => {
  if (!value) return <span className="empty-value">—</span>;

  const settings = control.settings ?? {};
  const format = settings.format ?? 'international';
  const formatted = formatPhoneNumber(value, format);

  return (
    <div className="phone-view">
      <a href={`tel:${value}`} aria-label={`Call ${formatted}`}>
        {formatted}
      </a>
    </div>
  );
};

Address View Example

export const AddressViewComponent: React.FC<ViewComponentProps> = ({ value }) => {
  if (!value) return <span>—</span>;

  const { street, city, state, zipCode } = value;

  return (
    <address style={{ fontStyle: 'normal' }}>
      <div>{street}</div>
      <div>{city}, {state} {zipCode}</div>
    </address>
  );
};

Empty State

Always handle null and undefined values gracefully in the view component. The recommended empty state is an em dash () in a muted style, consistent with Atlas Forms built-in display controls:

if (!value || value === '') {
  return <span className="text-muted">—</span>;
}

Accessibility in View Mode

View components should still be accessible: