---
sidebar_label: Advanced UI schema
toc_max_heading_level: 4
doc_id: a81db0c4-9e37-44a3-aaf7-2f3d8f2e87ba
description: Advanced UI schema features in nullplatform, including conditional rules (SHOW, HIDE, ENABLE, DISABLE), APPLY patches, and dynamic behavior.
keywords:
  - ui schema
  - rules
  - apply
  - jsonforms
  - conditional
  - form logic
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

# Advanced UI schema

This page covers **dynamic behavior** in UI schema, explaining how to make forms react to user input
using **rules** and **conditions**.

You’ll learn how to:
- Show or hide elements conditionally.
- Enable or disable fields dynamically.
- Patch labels and options using `APPLY` rules.

> 💡 If you’re new to UI schema, start with [Designing the UI schema](./ui-schema.md).


## Rules overview

Rules let you change the form layout or behavior based on data entered by the user.
They’re attached to any UI schema element through the `rule` property.

## Supported effects

| Rule      | Behavior when condition is true                           | Behavior when condition is false |
| --------- | --------------------------------------------------------- | -------------------------------- |
| `SHOW`    | Shows the element                                         | Hides the element                |
| `HIDE`    | Hides the element                                         | Shows the element                |
| `ENABLE`  | Enables the element                                       | Disables the element             |
| `DISABLE` | Disables the element                                      | Enables the element              |
| `APPLY`   | Dynamically patches UI properties (labels, options, etc.) | No changes applied               |


**In a nutshell:**  
- Use rules to make forms dynamic and context-aware.  
- `SHOW`, `HIDE`, `ENABLE`, and `DISABLE` control visibility and state,  
- while `APPLY` lets you adjust labels, options, and other UI properties on the fly.


## Visibility effect (SHOW / HIDE)

Use these rules to control **whether a field or section is visible** based on form data.
This is useful for revealing optional sections, toggles, or advanced settings.

```json
{
  "type": "Control",
  "scope": "#/properties/ssn",
  "rule": {
    "effect": "SHOW",
    "condition": {
      "scope": "#/properties/country",
      "schema": { "const": "USA" }
    }
  }
}
```

## State effect (ENABLE / DISABLE)

These rules control **whether a field is editable** depending on user input or permissions.
They are often used to lock or unlock inputs dynamically.


```json
{
  "type": "Control",
  "scope": "#/properties/comments",
  "rule": {
    "effect": "ENABLE",
    "condition": {
      "scope": "#/properties/allowComments",
      "schema": { "const": true }
    }
  }
}
```

## APPLY rules

`APPLY` rules dynamically modify UI schema properties based on **conditions**. This rule lets you **patch** UI schema
properties (like `label`, `options`, or `enabled`), depending on form state.

### Conditions

Conditions define **when** a rule is triggered. You can express simple or complex logic depending on your needs.

#### Schema condition (most common)

Validates a field value against a JSON Schema snippet.

```json
{
  "scope": "#/properties/country",
  "schema": { "const": "USA" }
}
```

Use:
- `const` for equality checks
- `enum`, `minimum`, `pattern`, etc., for more advanced validation



#### Logical conditions (AND / OR)

Combine multiple checks to express advanced logic.

```json
{
  "type": "AND",
  "conditions": [
    { "scope": "#/properties/isVIP", "schema": { "const": true } },
    { "scope": "#/properties/orders", "schema": { "minimum": 10 } }
  ]
}
```

```json
{
  "type": "OR",
  "conditions": [
    { "scope": "#/properties/tier", "schema": { "const": "gold" } },
    { "scope": "#/properties/tier", "schema": { "const": "platinum" } }
  ]
}
```

### APPLY rule examples

#### Single outcome (basic APPLY rule)

```json
{
  "type": "Control",
  "scope": "#/properties/quantity",
  "rule": {
    "effect": "APPLY",
    "condition": {
      "scope": "#/properties/inStock",
      "schema": { "const": false }
    },
    "outcome": {
      "enabled": false,
      "label": "Quantity (Out of stock)"
    }
  }
}
```

#### Multi-case outcomes

Evaluate multiple cases in order; the first match wins.
Provide a final fallback case without `condition`.

```json
{
  "type": "Control",
  "scope": "#/properties/field",
  "rule": {
    "effect": "APPLY",
    "cases": [
      {
        "condition": {
          "scope": "#/properties/mode",
          "schema": { "const": "basic" }
        },
        "outcome": {
          "label": "Basic Field",
          "options": { "multi": false }
        }
      },
      {
        "condition": {
          "scope": "#/properties/mode",
          "schema": { "const": "advanced" }
        },
        "outcome": {
          "label": "Advanced Field",
          "options": { "multi": true }
        }
      },
      {
        "outcome": {
          "label": "Default Field"
        }
      }
    ]
  }
}
```

#### Complex condition with logical operators

```json
{
  "type": "Control",
  "scope": "#/properties/discount",
  "rule": {
    "effect": "APPLY",
    "condition": {
      "type": "OR",
      "conditions": [
        {
          "scope": "#/properties/isVIP",
          "schema": { "const": true }
        },
        {
          "type": "AND",
          "conditions": [
            {
              "scope": "#/properties/orderCount",
              "schema": { "minimum": 10 }
            },
            {
              "scope": "#/properties/totalSpent",
              "schema": { "minimum": 1000 }
            }
          ]
        }
      ]
    },
    "outcome": {
      "options": {
        "showUnfocusedDescription": true
      }
    }
  }
}
```

#### Dynamic options (unset or override)

```json
{
  "type": "Control",
  "scope": "#/properties/password",
  "options": { "format": "password" },
  "rule": {
    "effect": "APPLY",
    "condition": {
      "scope": "#/properties/showPassword",
      "schema": { "const": true }
    },
    "outcome": { "options": { "format": null } }
  }
}
```

> 💡 Use `outcome.options` to tweak how a control renders **without duplicating elements**.


## Common dynamic patterns

Here are some frequent use cases for rules.

### Show a section when a toggle is on

```json
{
  "type": "Group",
  "label": "Delivery settings",
  "rule": {
    "effect": "SHOW",
    "condition": {
      "scope": "#/properties/delivery",
      "schema": { "const": true }
    }
  },
  "elements": [
    { "type": "Control", "scope": "#/properties/address" },
    { "type": "Control", "scope": "#/properties/window" }
  ]
}
```

### Enable a field only for admins

```json
{
  "type": "Control",
  "scope": "#/properties/limit",
  "rule": {
    "effect": "ENABLE",
    "condition": {
      "scope": "#/properties/isAdmin",
      "schema": { "const": true }
    }
  }
}
```

### Change a label based on selection

```json
{
  "type": "Control",
  "scope": "#/properties/name",
  "rule": {
    "effect": "APPLY",
    "cases": [
      {
        "condition": {
          "scope": "#/properties/type",
          "schema": { "const": "person" }
        },
        "outcome": { "label": "Full name" }
      },
      {
        "condition": {
          "scope": "#/properties/type",
          "schema": { "const": "company" }
        },
        "outcome": { "label": "Company name" }
      },
      { "outcome": { "label": "Name" } }
    ]
  }
}
```


### Adjust options based on other data

```json
{
  "type": "Control",
  "scope": "#/properties/region",
  "rule": {
    "effect": "APPLY",
    "condition": {
      "scope": "#/properties/country",
      "schema": { "enum": ["US", "CA"] }
    },
    "outcome": {
      "options": { "placeholder": "Pick a region (US/CA)" }
    }
  }
}
```

## Troubleshooting and tips
- Rules are evaluated in order from top to bottom within each layout.
- Use function-based conditions only for exceptional edge cases.
- If rules don’t seem to apply, confirm that your `scope` paths match the JSON Schema.
