Table of Contents

JSON Schema Form Customisation Guide

Altus uses a JSON Schema-driven form engine to render settings and configuration screens. This engine is built on the open-source react-jsonschema-form (RJSF) library, extended with Altus-specific custom widgets for Dataverse integration.

This guide explains how to use JSON Schema and UI Schema to customise existing Altus settings or define your own configuration forms.


Core Concepts

Every form is defined by two JSON documents:

Document Purpose
Schema (schema.json) Defines the data structure, field types, validation rules, and default values.
UI Schema (uiSchema.json) Controls how each field is rendered — which widget to use, layout options, and display behaviour.

The schema determines what data is captured. The UI schema determines how it appears to the user.

For comprehensive documentation on the base JSON Schema capabilities, refer to the RJSF JSON Schema documentation.


Schema Basics

Field Types

JSON Schema supports the following base field types:

  • string — Text input
  • number — Decimal number input
  • integer — Whole number input
  • boolean — True/false toggle
  • object — A group of named properties
  • array — A list of items

For full details, see the RJSF Single Fields documentation.

Simple Field Example

{
  "type": "object",
  "properties": {
    "projectName": {
      "type": "string",
      "title": "Project Name"
    },
    "maxHours": {
      "type": "integer",
      "title": "Maximum Hours"
    },
    "isActive": {
      "type": "boolean",
      "title": "Active"
    }
  },
  "required": ["projectName"]
}

This schema produces a form with a required text field, a number field, and a toggle.

Titles and Descriptions

Use title and description on any property to provide a label and helper text:

{
  "projectName": {
    "type": "string",
    "title": "Project Name",
    "description": "Enter the display name for this project."
  }
}

Default Values

Set initial values with the default keyword:

{
  "maxHours": {
    "type": "integer",
    "title": "Maximum Hours",
    "default": 40
  }
}

Enumerated Values

Restrict a field to a fixed set of choices using enum:

{
  "priority": {
    "type": "string",
    "title": "Priority",
    "enum": ["Low", "Medium", "High", "Critical"]
  }
}

To provide custom display labels for enum values, use oneOf with const and title:

{
  "status": {
    "type": "number",
    "title": "Status",
    "oneOf": [
      { "const": 1, "title": "Draft" },
      { "const": 2, "title": "In Progress" },
      { "const": 3, "title": "Complete" }
    ]
  }
}

For more on enumerations, see the RJSF Enumerated Values documentation.

Objects (Grouped Properties)

Group related fields together using object type:

{
  "type": "object",
  "title": "Notification Settings",
  "properties": {
    "emailEnabled": {
      "type": "boolean",
      "title": "Enable Email Notifications"
    },
    "recipientCount": {
      "type": "integer",
      "title": "Max Recipients"
    }
  }
}

For more, see the RJSF Objects documentation.

Arrays (Lists of Items)

Define repeating items with array type:

{
  "milestones": {
    "type": "array",
    "title": "Milestones",
    "items": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "title": "Milestone Name"
        },
        "dueDate": {
          "type": "string",
          "title": "Due Date",
          "format": "date"
        }
      }
    }
  }
}

For more, see the RJSF Arrays documentation.

Required Fields

Mark fields as mandatory using the required keyword on the parent object:

{
  "type": "object",
  "properties": {
    "name": { "type": "string", "title": "Name" },
    "email": { "type": "string", "title": "Email" }
  },
  "required": ["name", "email"]
}

UI Schema Basics

The UI Schema controls the visual presentation of each field. It mirrors the structure of the data schema and uses special ui: prefixed keys.

Assigning a Widget

Use ui:widget to specify which control renders a field:

{
  "fieldName": {
    "ui:widget": "EntityLookupWidget",
    "ui:options": {
      "endPoint": "sensei_projects",
      "valueField": "sensei_projectid",
      "nameField": "sensei_name"
    }
  }
}

Hiding a Field

{
  "internalId": {
    "ui:widget": "hidden"
  }
}

Field Order

Control the display order of fields using ui:order:

{
  "ui:order": ["name", "priority", "description", "*"]
}

The wildcard * places all remaining fields at that position.

Placeholder Text

{
  "notes": {
    "ui:placeholder": "Enter your notes here..."
  }
}

Read-Only Fields

{
  "createdBy": {
    "ui:readonly": true
  }
}

For the full list of standard UI Schema options, refer to the RJSF UI Schema documentation.


Altus Custom Widgets

In addition to the standard form controls, Altus provides custom widgets designed for Dataverse integration and specialised input scenarios. Use these by setting ui:widget to the widget name and passing configuration through ui:options.

Important

Widget names are case-sensitive. Always use the exact names listed below.

EntityLookupWidget

A single-record lookup that searches a Dataverse table. Displays a tag picker allowing the user to search and select one record.

Value stored: Record ID (GUID string) or null.

Required options:

Option Description
endPoint Dataverse table logical collection name (e.g. sensei_projects)
valueField The ID field of the target table (e.g. sensei_projectid)
nameField The field used as the display label (e.g. sensei_name)

Optional options:

Option Default Description
additionalSearchFilter Additional OData filter to narrow search results
supportsContains true Whether the search supports contains-style filtering
provider false Publishes the selected value for dependent fields (see Provider/Consumer Pattern)
consumer Disables this field until the referenced provider field has a value

Example:

{
  "schema": {
    "type": "object",
    "properties": {
      "project": {
        "type": "string",
        "title": "Project"
      }
    }
  },
  "uiSchema": {
    "project": {
      "ui:widget": "EntityLookupWidget",
      "ui:options": {
        "endPoint": "sensei_projects",
        "valueField": "sensei_projectid",
        "nameField": "sensei_name"
      }
    }
  }
}

EntityLookupArrayWidget

A multi-select record lookup. Displays a tag picker allowing the user to search and select multiple records.

Value stored: Array of record IDs (GUID strings) or null.

Options: Same as EntityLookupWidget, plus:

Option Description
readOnlyItems Array of record IDs that cannot be removed by the user

Example:

{
  "teamMembers": {
    "ui:widget": "EntityLookupArrayWidget",
    "ui:options": {
      "endPoint": "systemusers",
      "valueField": "systemuserid",
      "nameField": "fullname"
    }
  }
}

OptionSetWidget

A dropdown populated from a Dataverse option set (choice column).

Value stored: Option set value as a string (e.g. "100000001").

Required options:

Option Description
optionSetName The logical name of the global option set, or the attribute logical name for local option sets

Optional options:

Option Default Description
entity none Required for local (entity-specific) option sets. Set to the table logical name.
provider false Publishes the selected value for dependent fields
consumer Disables this field until the referenced provider field has a value

Example — Global option set:

{
  "kpiField": {
    "ui:widget": "OptionSetWidget",
    "ui:options": {
      "optionSetName": "sensei_overallprojectkpi"
    }
  }
}

Example — Local (entity-specific) option set:

{
  "statusField": {
    "ui:widget": "OptionSetWidget",
    "ui:options": {
      "optionSetName": "statuscode",
      "entity": "incident"
    }
  }
}

CheckboxWidget

A toggle switch for boolean fields, rendered as a Fluent UI toggle control.

Value stored: true or false.

Optional UI Schema keys:

Key Default Description
offText No Label shown when the toggle is off
onText Yes Label shown when the toggle is on

Example:

{
  "enableSync": {
    "ui:widget": "CheckboxWidget",
    "offText": "Disabled",
    "onText": "Enabled"
  }
}

CheckboxesWidget

A multi-select checkbox group for fields with enumerated values.

Value stored: Array of selected enum values.

Example:

Schema:

{
  "enabledFeatures": {
    "type": "array",
    "title": "Enabled Features",
    "items": {
      "type": "string",
      "enum": ["Reporting", "Notifications", "Approvals"]
    },
    "uniqueItems": true
  }
}

UI Schema:

{
  "enabledFeatures": {
    "ui:widget": "CheckboxesWidget"
  }
}

SelectWidget

A dropdown for fields with enumerated values, rendered as a Fluent UI dropdown.

Value stored: The selected enum value (or array of values for multi-select).

Example:

{
  "priority": {
    "ui:widget": "SelectWidget"
  }
}

TextWidget

A text input that can optionally render as a combo box when the schema defines examples. Supports additional Fluent UI text field properties.

Value stored: String.

Example — Multiline text area:

{
  "notes": {
    "ui:widget": "TextWidget",
    "ui:options": {
      "props": {
        "multiline": true,
        "rows": 4,
        "placeholder": "Add notes"
      }
    }
  }
}

ReadOnlyTextWidget

Displays text as read-only. Supports inline bold formatting using **text** syntax within the value.

Value stored: String.

Example:

{
  "instructions": {
    "ui:widget": "ReadOnlyTextWidget"
  }
}

A stored value of "Use **project defaults** for baseline setup." renders with "project defaults" in bold.

FormattedIntegerWidget

An integer input that displays a visual prefix or suffix while storing only the numeric value.

Value stored: Integer.

Optional options:

Option Description
displayPrefix Text shown before the number (e.g. $)
displaySuffix Text shown after the number (e.g. % or hrs)

Example:

{
  "hoursPerWeek": {
    "ui:widget": "FormattedIntegerWidget",
    "ui:options": {
      "displaySuffix": " hrs"
    }
  }
}

ColourPickerWidget

A colour class selector used for capacity and legend colour coding. Presents a set of predefined colour classes.

Value stored: CSS class name string (e.g. altus-rh-capacity-level--4).

Note

This widget uses a fixed set of colour classes (altus-rh-capacity-level--0 through altus-rh-capacity-level--12). It is different from the built-in color widget.

Example:

{
  "capacityColor": {
    "ui:widget": "ColourPickerWidget"
  }
}

Built-In Widgets

In addition to the Altus custom widgets above, the following standard widgets from the RJSF library are available:

Widget Description
text Standard single-line text input
textarea Multi-line text input
checkbox Standard HTML checkbox
color Browser colour picker
hidden Hidden field (not displayed)

Use built-in widgets when custom Dataverse integration or specialised rendering is not required.


Provider/Consumer Pattern

The provider/consumer pattern creates dependencies between fields. When a provider field has a value selected, dependent consumer fields become enabled. This is useful when one field's options depend on another field's selection.

How it works:

  1. Mark the source field with "provider": true in its ui:options.
  2. Mark the dependent field with "consumer": "root_<providerFieldName>" in its ui:options.
  3. The consumer field remains disabled until the provider field has a value.

Example:

{
  "kpiField": {
    "ui:widget": "EntityLookupWidget",
    "ui:options": {
      "provider": true,
      "endPoint": "sensei_kpifields",
      "valueField": "sensei_kpifieldid",
      "nameField": "sensei_name"
    }
  },
  "kpiValue": {
    "ui:widget": "OptionSetWidget",
    "ui:options": {
      "consumer": "root_kpiField",
      "optionSetName": "sensei_kpivalue"
    }
  }
}

In this example, the KPI Value dropdown is disabled until a KPI Field is selected.


Layout Extensions

Altus extends the standard RJSF layout with options to control field width and alignment.

Full Width

Force a field to span the full width of the form. This can be set in either the schema or the UI schema:

In the schema:

{
  "description": {
    "type": "string",
    "fullWidth": true
  }
}

Or in the UI schema:

{
  "description": {
    "fullWidth": true
  }
}

Half Width

Keep a field at half width (the default for most fields):

{
  "compactField": {
    "halfWidth": true
  }
}

Left-Aligned Row

Take a full row but keep the content left-aligned with whitespace on the right:

{
  "sectionHeader": {
    "leftAlignedRow": true
  }
}

Array Presentation Options

Altus provides enhanced rendering options for array fields, controlled through the UI schema.

Dialog-Based Editing

Display array items in a summary table, with each item opening in a dialog for editing:

{
  "initiativeTypes": {
    "useArrayItemDialog": true,
    "arrayTableColumns": ["table", "lookupField", "tabLabel"],
    "noItemsText": "Select **Edit Defaults** to customise or add a new item."
  }
}
Option Description
useArrayItemDialog When true, array items are shown in a table with row editing via a dialog
arrayTableColumns Array of property names controlling which columns appear and their order
noItemsText Custom text shown when the array is empty (supports markdown)

Inline Table Editing

Display array items directly in an editable table:

{
  "evaluationPoints": {
    "useArrayInlineTable": true,
    "items": {
      "useArrayInlineTableRow": true
    }
  }
}
Option Description
useArrayInlineTable When true, renders the array as an inline editable table
useArrayInlineTableRow Set on the items node to render object fields as table cells

Complete Example

Below is a complete example combining schema and UI schema to create a settings form with Dataverse lookups, option sets, and layout controls.

Schema:

{
  "type": "object",
  "title": "Risk Configuration",
  "properties": {
    "riskCategory": {
      "type": "string",
      "title": "Risk Category"
    },
    "severity": {
      "type": "string",
      "title": "Severity"
    },
    "enableNotifications": {
      "type": "boolean",
      "title": "Enable Notifications",
      "default": true
    },
    "maxRiskScore": {
      "type": "integer",
      "title": "Maximum Risk Score",
      "default": 100
    },
    "notes": {
      "type": "string",
      "title": "Notes",
      "fullWidth": true
    },
    "thresholds": {
      "type": "array",
      "title": "Risk Thresholds",
      "items": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string",
            "title": "Label"
          },
          "minScore": {
            "type": "integer",
            "title": "Minimum Score"
          },
          "colour": {
            "type": "string",
            "title": "Colour"
          }
        },
        "required": ["label", "minScore"]
      }
    }
  },
  "required": ["riskCategory"]
}

UI Schema:

{
  "ui:order": ["riskCategory", "severity", "enableNotifications", "maxRiskScore", "notes", "thresholds"],
  "riskCategory": {
    "ui:widget": "EntityLookupWidget",
    "ui:options": {
      "endPoint": "sensei_riskcategories",
      "valueField": "sensei_riskcategoryid",
      "nameField": "sensei_name"
    }
  },
  "severity": {
    "ui:widget": "OptionSetWidget",
    "ui:options": {
      "optionSetName": "sensei_riskseverity"
    }
  },
  "enableNotifications": {
    "ui:widget": "CheckboxWidget",
    "onText": "On",
    "offText": "Off"
  },
  "maxRiskScore": {
    "ui:widget": "FormattedIntegerWidget",
    "ui:options": {
      "displaySuffix": " pts"
    }
  },
  "notes": {
    "ui:widget": "TextWidget",
    "ui:options": {
      "props": {
        "multiline": true,
        "rows": 3,
        "placeholder": "Additional notes..."
      }
    }
  },
  "thresholds": {
    "useArrayInlineTable": true,
    "items": {
      "useArrayInlineTableRow": true,
      "colour": {
        "ui:widget": "ColourPickerWidget"
      }
    }
  }
}

Quick Reference

Widget Summary

Widget Use Case Value Type
EntityLookupWidget Single Dataverse record lookup GUID string
EntityLookupArrayWidget Multi-select Dataverse record lookup GUID string array
OptionSetWidget Dataverse option set dropdown Option value string
CheckboxWidget Boolean toggle Boolean
CheckboxesWidget Multi-select checkboxes Value array
SelectWidget Enum dropdown Enum value
TextWidget Text input with optional combo box String
ReadOnlyTextWidget Read-only text display String
FormattedIntegerWidget Integer with display prefix/suffix Integer
ColourPickerWidget Colour class selector CSS class string

Common UI Schema Keys

Key Description
ui:widget Specifies the widget to render
ui:options Widget-specific configuration
ui:order Controls field display order
ui:placeholder Placeholder text
ui:readonly Makes a field read-only
ui:title Overrides the schema title
ui:description Overrides the schema description
fullWidth Forces full-width layout
halfWidth Forces half-width layout
leftAlignedRow Full row, left-aligned content

Further Reading