> For the complete documentation index, see [llms.txt](https://docs.valorx.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.valorx.com/valorx-wave/surf-the-wave/publish-the-grid/dynamic-grid.md).

# Dynamic Grid

&#x20;The Wave Dynamic Grid lets a single grid adapt its columns per record. Instead of building a separate grid for every field requirement, you define one grid and then drive what it shows using a JSON configuration stored on the parent record.

<figure><img src="/files/eYRm0JGsEyfV9xM5sTRE" alt=""><figcaption></figcaption></figure>

### How It Works

{% stepper %}
{% step %}

#### Define your JSON config on the parent record

Include a 'fields' array that lists every column you want to show, with its rules and settings.
{% endstep %}

{% step %}

#### Grid loads and reads the config

When the grid component renders, it reads the JSON and builds the columns on the fly.
{% endstep %}

{% step %}

#### Users see the right fields

Only the configured columns appear in the right order, with the right access rules applied.
{% endstep %}
{% endstepper %}

### Field Access Types

Each field in the configuration is assigned one of the following access types:

<table><thead><tr><th width="161">Access Type</th><th>Behavior</th></tr></thead><tbody><tr><td>Mandatory</td><td>Field must be filled in. Displayed with a red cell background when empty.</td></tr><tr><td>Read-Only</td><td>Field is visible but cannot be edited in the grid.</td></tr><tr><td>Read/Write</td><td>Field is fully editable.</td></tr></tbody></table>

{% hint style="info" %}

#### Good to know

If a user makes changes (like filters or rules) after a config is applied, a personal copy is created to preserve those. When the parent record config is updated and a hard refresh is done, the grid honours the latest JSON.
{% endhint %}

{% hint style="danger" %}

#### Error handling

If all fields in your config are invalid, the grid shows an error screen instead of rendering. Fix at least one valid field ID to recover.
{% endhint %}

## Field Configuration JSON

The config is a JSON object with two required properties: **mode** and at least one entry in the fields array with **a valid id**. The mode property controls how the grid handles existing fields. All other field properties are optional. If omitted, the existing configuration is used; if included with an invalid value, the entire field is dropped.

### Append Mode vs Replace Mode

Set the mode property to control whether the JSON adds on top of the existing grid or fully replaces it.

<table><thead><tr><th valign="top">➕  "mode": "append"</th><th valign="top">🔄  "mode": "replace"</th></tr></thead><tbody><tr><td valign="top"><p>Existing fields stay. Any field in the JSON that matches an existing one gets updated; any new field gets added.</p><p><em>Use when you want to add or tweak a few columns without touching the rest.</em></p></td><td valign="top"><p>Removes all existing fields. Only the fields in the JSON are shown.</p><p><em>Use when you want to define the exact set of columns; no more, no less.</em></p></td></tr></tbody></table>

<table><thead><tr><th width="195"></th><th>➕  Append mode</th><th>🔄  Replace mode</th></tr></thead><tbody><tr><td>What happens to existing fields</td><td>All existing fields are kept. The JSON either updates a matching field (by ID) or adds a new one.</td><td>All existing fields are removed. Only the fields defined in the JSON are shown.</td></tr><tr><td>New field in JSON (not in grid yet)</td><td>Added to the grid.</td><td>Added to the grid.</td></tr><tr><td>Field in JSON that already exists</td><td>Updated with the properties defined in the JSON.</td><td>Replaced with the properties defined in the JSON.</td></tr><tr><td>Field in grid but not in JSON</td><td>Kept — untouched.</td><td>Removed.</td></tr><tr><td>Sequence / ordering</td><td>JSON sequence is honored. Fields without a sequence are placed last by JSON order.</td><td>JSON sequence is honored. Fields without a sequence are placed last by JSON order.</td></tr><tr><td>Typical use case</td><td>Add or update a few columns without disturbing the rest of the grid.</td><td>Define the exact set of columns to show; no more, no less.</td></tr></tbody></table>

### Append Mode — Example

**Append mode** adds and updates fields in an existing grid while preserving the current configuration. It allows you to add new fields, modify existing field settings, and reorder fields without recreating the entire grid.

```json
{
  "mode": "append",
  "fields": [
    {
      "id": "Name",
      "label": "Opportunity Product Name",
      "isReadOnly": false,
      "isRequired": true,
      "isHidden": false,
      "sequence": 1
    },
    {
      "id": "Product2.Name",
      "label": "Product",
      "isReadOnly": false,
      "isRequired": false,
      "isHidden": true
    },
    {
      "id": "Quantity",
      "label": "Quantity To Display",
      "isReadOnly": true,
      "isRequired": false,
      "isHidden": false,
      "sequence": 2,
      "backgroundColor": "#FFCDE8"
    },
    {
      "id": "TotalPrice",
      "label": "Total Price",
      "isReadOnly": false,
      "isRequired": false,
      "isHidden": false,
      "backgroundColor": "#D2B8FD"
    },
    {
      "id": "UnitPrice",
      "label": "Sales Price",
      "isReadOnly": false,
      "isRequired": false,
      "isHidden": false,
      "sequence": 3
    }
  ]
}
```

**Result**: The existing grid fields are retained. The **Name** fields are updated, **Quantity** is added as a new field, and the **Product** field is hidden. The field order is updated according to the specified sequence values.

<div><figure><img src="/files/nAWmCYv11zfKnpQkDXe0" alt=""><figcaption><p>Before Append</p></figcaption></figure> <figure><img src="/files/spP6braY5QtwDHbYXjmW" alt=""><figcaption><p>After Append</p></figcaption></figure></div>

### Replace Mode — Example

**Replace mode** replaces the existing grid configuration with the fields specified in the configuration. Any existing fields that are not included in the configuration are removed, and the grid is rebuilt based on the provided field definitions and settings.

```json
{
  "mode": "replace",
  "fields": [
    {
      "id": "Name",
      "label": "Opportunity Product Name",
      "isReadOnly": false,
      "isRequired": true,
      "isHidden": false,
      "sequence": 1
    },
    {
      "id": "Product2.Name",
      "label": "Product",
      "isReadOnly": false,
      "isRequired": false,
      "isHidden": true
    },
    {
      "id": "Quantity",
      "label": "Quantity To Display",
      "isReadOnly": true,
      "isRequired": false,
      "isHidden": false,
      "sequence": 2,
      "backgroundColor": "#FFCDE8"
    },
    {
      "id": "TotalPrice",
      "label": "Total Price",
      "isReadOnly": false,
      "isRequired": false,
      "isHidden": false,
      "backgroundColor": "#D2B8FD"
    },
    {
      "id": "UnitPrice",
      "label": "Sales Price",
      "isReadOnly": false,
      "isRequired": false,
      "isHidden": false,
      "sequence": 3
    }
  ]
}
```

**Result**: All original fields are removed and replaced with the fields defined in the configuration. The grid displays four fields because the **Product** field is configured as hidden. The field order is updated according to the specified sequence values.

<div><figure><img src="/files/yqprn1xBabDuOoOFf4uG" alt=""><figcaption><p>Before Replace</p></figcaption></figure> <figure><img src="/files/hyc3zuYEmofLvhkigazT" alt=""><figcaption><p>After Replace</p></figcaption></figure></div>

### Property Reference

<table data-header-hidden><thead><tr><th width="174" valign="top"></th><th valign="top"></th></tr></thead><tbody><tr><td valign="top">id</td><td valign="top"><strong>String</strong>  <strong>·  Required</strong>  — Must match the Salesforce field API name, case-sensitive. Fields with a missing or empty id is dropped.</td></tr><tr><td valign="top">label</td><td valign="top"><strong>String</strong> <strong>·  Optional</strong>  — Overrides the column header text. If invalid, the field is dropped.</td></tr><tr><td valign="top">isReadOnly</td><td valign="top"><strong>Boolean</strong>  <strong>·  Optional</strong> — Show the field but block editing. If invalid, the field is dropped.</td></tr><tr><td valign="top">isRequired</td><td valign="top"><strong>Boolean</strong>  <strong>·  Optional</strong> — Require a value before the row saves. If invalid, the field is dropped.</td></tr><tr><td valign="top">isHidden</td><td valign="top"><strong>Boolean</strong>  <strong>·  Optional</strong>  — Hide the field from the grid entirely. If invalid, the field is dropped.</td></tr><tr><td valign="top">sequence</td><td valign="top"><strong>Integer > 0</strong> <strong>·  Optional</strong> — Column position. If provided, it is honored; if omitted, the field is placed last based on its order in the JSON</td></tr><tr><td valign="top">backgroundColor</td><td valign="top"><strong>Hex string  ·  Optional</strong>  — Column background color. Snaps to the nearest theme color if exact match not found.</td></tr></tbody></table>

{% hint style="warning" %}
**Note:** When no key is specified, the existing configuration is automatically selected and used.

Each field is validated independently. If no valid field is found (the fields array is empty, missing, or all entries have invalid IDs), the grid displays an error screen instead of rendering.
{% endhint %}

### JSON Format

The first object below is a minimal configuration (inherits all settings); the second specifies every property explicitly. When passed to the component, this object must be serialised as a JSON string.&#x20;

```json
{
  "fields": [
    { "id": "TotalPrice" },
    {
      "id": "Name",
      "label": "Total Price",
      "isReadOnly": false,
      "isRequired": false,
      "isHidden": false,
      "sequence": 3,
      "backgroundColor": "#FFB0D0"
    }
  ]
}
```

## Background Color Support

The backgroundColor property lets you set a column background using any hex code. If the hex doesn't match a theme color exactly, Wave automatically snaps it to the closest match.

<div><figure><img src="/files/wyfQgvpWchyngQYJpOEN" alt=""><figcaption><p>Before</p></figcaption></figure> <figure><img src="/files/hCBs2x5TmsPEAvDRcg1E" alt=""><figcaption><p>After</p></figcaption></figure></div>

### Rule Precedence

If a background color and a conditional formatting rule are both applied to the same column, the rule takes precedence and the background color is overridden for rows where the rule condition is met.

{% hint style="info" %}
Rules always take precedence over backgroundColor. The configured background color remains visible for rows where no rule condition is triggered.
{% endhint %}

### Setting a Background Color

Set the backgroundColor property to any valid hex code:

```json
{
  "id": "Amount__c",
  "label": "Amount",
  "isReadOnly": false,
  "backgroundColor": "#FFD700"
}
```

If #FFD700 isn't in the theme palette, Wave picks the nearest available color automatically — you don't need to do anything.

### Supported Theme Colors

These are the exact hex codes that are honoured without snapping. Editable and read-only fields use separate palettes.

{% hint style="info" %}
If the specified hex code does not exactly match a color in the available palette, the closest matching color from the palette is applied automatically. Exact hex codes are honored only for Valorx theme colors.
{% endhint %}

#### Coral

<figure><img src="/files/iAnsIGUXh8rNVweZdkNk" alt=""><figcaption></figcaption></figure>

| #FFD8DE | #FFD1D7 | #FFCDE8 | #FFB8DE | #FFA8CC |
| :-----: | :-----: | :-----: | :-----: | :-----: |

#### Pink

<figure><img src="/files/s4fhayroVznN9Mu4G6Co" alt=""><figcaption></figcaption></figure>

| #FFD6FA | #FFC7F3 | #FFBDF8 | #FBCCFF | #F5B8FF |
| :-----: | :-----: | :-----: | :-----: | :-----: |

#### Sunset

<figure><img src="/files/MuFemUh2ApsHIdgovmEb" alt=""><figcaption></figcaption></figure>

| #F5DDD6 | #F9C8BE | #FFC2BC | #F0C4C4 | #FFADA6 |
| :-----: | :-----: | :-----: | :-----: | :-----: |

#### Yellow&#x20;

<figure><img src="/files/RFmcuFc5gVPTem021Mga" alt=""><figcaption></figcaption></figure>

| #FEEDBF | #FFF0B3 | #FFE8A0 | #FFE091 | #FFD4AE |
| :-----: | :-----: | :-----: | :-----: | :-----: |

#### Lime&#x20;

<figure><img src="/files/9PmdamgbvOHUWegM0iBC" alt=""><figcaption></figcaption></figure>

| #EEF5C4 | #F0F9A8 | #FAFFBE | #E4EEAA | #E6FFC7 |
| :-----: | :-----: | :-----: | :-----: | :-----: |

#### Green&#x20;

<figure><img src="/files/VfZWjDASKMlfqwabL33s" alt=""><figcaption></figcaption></figure>

| #DDE5CC | #D5E5CC | #D4EBCA | #C8F0C4 | #C7EFAF |
| :-----: | :-----: | :-----: | :-----: | :-----: |

#### Teal&#x20;

<figure><img src="/files/zOAKow0A5QJ4G3KQD51F" alt=""><figcaption></figcaption></figure>

| #BEE8D6 | #CFEFE1 | #D6F5DF | #C7FFE1 | #AEFFD4 |
| :-----: | :-----: | :-----: | :-----: | :-----: |

#### Mint&#x20;

<figure><img src="/files/ujwjmJDcMDyUU5dIBlll" alt=""><figcaption></figcaption></figure>

| #D6F7F7 | #C5F0F0 | #C4F0F0 | #AFEFEF | #9FE8E8 |
| :-----: | :-----: | :-----: | :-----: | :-----: |

#### Aqua&#x20;

<figure><img src="/files/AeH1q0HS4vTjGXZ8wQgU" alt=""><figcaption></figcaption></figure>

| #D6F0F8 | #C8EBFC | #C4E8F0 | #B8E4F2 | #ADE0EE |
| :-----: | :-----: | :-----: | :-----: | :-----: |

#### Blue&#x20;

<figure><img src="/files/qNnrygTBgiDrLl8rnZuo" alt=""><figcaption></figcaption></figure>

| #E2EDFF | #D6E1F5 | #CFDEFA | #D1DEFF | #BDD4FF |
| :-----: | :-----: | :-----: | :-----: | :-----: |

#### Purple&#x20;

<figure><img src="/files/8feJAsd53RskpWeFYxCr" alt=""><figcaption></figcaption></figure>

| #E9EAFF | #D5DAFF | #C7CDFF | #B4BCFF | #A8B2FF |
| :-----: | :-----: | :-----: | :-----: | :-----: |

#### Violet&#x20;

<figure><img src="/files/IYfLDt8KGNc7ZvvGsVEU" alt=""><figcaption></figcaption></figure>

| #E7DAFC | #EBD6F5 | #E0C7FF | #D2B8FD | #C3C4F0 |
| :-----: | :-----: | :-----: | :-----: | :-----: |

#### Cool Tan&#x20;

<figure><img src="/files/yBEGvX7YmYhvbL8v3nYR" alt=""><figcaption></figcaption></figure>

| #F5EFE0 | #F2EAD2 | #EDE4C5 | #E8DCBA | #E0D7B8 |
| :-----: | :-----: | :-----: | :-----: | :-----: |

#### Warm Tan&#x20;

<figure><img src="/files/u88GDYRMLV2EsYbPeSpw" alt=""><figcaption></figcaption></figure>

| #F7EDD0 | #F3E5BF | #EEDCAC | #E8D49A | #F0D090 |
| :-----: | :-----: | :-----: | :-----: | :-----: |

#### Cool Gray&#x20;

<figure><img src="/files/jidIxsk1lCT0lJGUmGO1" alt=""><figcaption></figcaption></figure>

| #D9DBE0 | #E8E9F4 | #DCDDED | #CDD0E4 | #C4C7DA |
| :-----: | :-----: | :-----: | :-----: | :-----: |

#### Warm Gray&#x20;

<figure><img src="/files/JLbfMCSr8WiusuxHIfgE" alt=""><figcaption></figcaption></figure>

| #E4E1DC | #D8D6D2 | #CECAC4 | #C9C9C9 | #BFBCB8 |
| :-----: | :-----: | :-----: | :-----: | :-----: |

#### Gray (Read-only)

<figure><img src="/files/KtFuzzimY14L5trpa8GG" alt=""><figcaption></figcaption></figure>

| #F2F2F2 | #ECEFEC | #E5E5E5 | #D8D8D8 | #C9CACE |
| :-----: | :-----: | :-----: | :-----: | :-----: |

#### Cool Gray (Read-only)

<figure><img src="/files/gJ2kXkqP7Y0V5fXJfiM0" alt=""><figcaption></figcaption></figure>

| #F2EFF0 | #EFF3ED | #E3E7E5 | #DEE5E9 | #A8B4BC |
| :-----: | :-----: | :-----: | :-----: | :-----: |

#### Warm Gray (Read-only)

<figure><img src="/files/R4m7MblEGLzVuTEjnUVV" alt=""><figcaption></figcaption></figure>

| #EEEBF1 | #E5E3E5 | #DEDBD3 | #C8C0B4 | #A09080 |
| :-----: | :-----: | :-----: | :-----: | :-----: |

## Passing Configuration to the Valorx Grid Component

Both the Aura grid and the LWC grid accept the configuration through the gridConfig property. Bind it to an attribute or property that holds your serialized JSON string. The grid re-renders automatically when the value changes.

### Aura Grid&#x20;

Component name: `(valorxwave:ValorxRapidGrid)`

```html
<valorxwave:ValorxRapidGrid
  gridId="{!v.gridId}"
  gridConfig="{!v.gridConfig}" />
```

### LWC Grid (valorxGrid)

Component name (managed package, subscriber org): `c-valorxwave-valorx-grid`

```html
<c-valorxwave-valorx-grid
  grid-id={gridId}
  grid-config={gridConfig}>
</c-valorxwave-valorx-grid>
```

{% hint style="info" %}
If a previously saved configuration is loaded on init and assigned to gridConfig, the grid applies it automatically when the component renders.
{% endhint %}

## Runtime Updates via Lightning Message Service (LMS)

If a previously saved configuration is loaded on init and assigned to gridConfig, the grid applies it automatically when the component renders.

&#x20;Chanel Name: `valorxwave__callbackMessageChannel__c`

### Message Payload

<table><thead><tr><th width="148">Property</th><th width="153">Type</th><th>Description</th></tr></thead><tbody><tr><td>value</td><td>String</td><td>Serialised JSON configuration.</td></tr><tr><td>status</td><td>String</td><td>SUCCESS or ERROR.</td></tr><tr><td>data</td><td>String</td><td>Set to RowActionCompleted to trigger a grid update.</td></tr></tbody></table>

#### Example

```
{
  "value": "{\"fields\":[{\"id\":\"TotalPrice\"}]}",
  "status": "SUCCESS",
  "data": "RowActionCompleted"
}
```

{% hint style="danger" %}

#### Important

The grid subscribes at APPLICATION scope, allowing any component on the page to publish configuration updates. If multiple grids exist on the same page, all grids receive the message. Add filtering logic if only specific grids should respond.
{% endhint %}
