# Observable Format Column Conditions

Canonical page: https://www.adaptabletools.com/docs/handbook-column-formatting-conditions-observable

- Observable Conditions style (or format) a cell while a live [Observable Expression](https://www.adaptabletools.com/docs/adaptable-ql-expression-observable/index.md) Rule is true
- They are ideal for history / time visuals — e.g. stale cells, busy windows, net moves, highs / lows
- Scope, Style and Display Format work the same as for Standard Conditions

Most [Format Column Conditions](https://www.adaptabletools.com/docs/handbook-column-formatting-conditions/index.md) use changes to apply the Condition.

However it is also possible to use Observable Expressions for Conditional Styles.

When this happens, formatting tracks **how** data has changed over time — not only the current value.

- There is no persisted Condition Type on the Format Column (as in other objects like Calculated Columns)
- Instead, AdapTable infers Standard vs Observable from the Rule text (Observable Functions use curly braces)

The Conditional Style Rule is a boolean Expression built from [Observable Functions](https://www.adaptabletools.com/docs/adaptable-ql-expression-observable/index.md), for example:

```ts [[2, 1, "NO_CHANGES"], [1, 1, "github_stars"], [2, 1, "WITHIN"], [4, 1, "5s"]]
 NO_CHANGES{[github_stars], WITHIN(5s)}
```

```ts [[2, 1, "NET_CHANGE"], [1, 1, "github_stars"], [2, 1, "WITHIN"], [4, 1, "30s"]]
 NET_CHANGE{[github_stars], WITHIN(30s)} > 20
```

- Windowed and clock-based Conditions will keep re-evaluating 
- This will happen so long as `liveRefreshIntervalMs` is greater than `0` (the default value is `1000`)

## Stale cells

It is possible to style a cell when it has **not** changed recently.

This is very useful for spotting silence in ticking data

**Example: Observable Condition: Stale Cells**

Grey out Github Stars when there are no changes for 5 seconds

- Format Column Rule: `NO_CHANGES{[github_stars], WITHIN(5s)}`
- `Github Stars` ticks every second while the feed is on — cells stay unstyled
- Click **Turn off Ticking Data**, wait 5 seconds, and cells turn grey

Demo project (Vanilla); the files without a marker are shown below:

```text
src/
  adaptableOptions.ts
  agGridModules.ts      [template]
  columnDefs.ts         [template]
  gridOptions.ts        [template]
  index.ts              [template]
  onAdaptableReady.ts
  rowData.ts            [template]
  styles.css            [template]
  tickingDataHelper.ts  [template]
index.html              [template]
package.json            [template]
tsconfig.json           [template]
```

Files marked `[template]` are the same in every demo; see the [demo template](https://www.adaptabletools.com/llms/demo-template.md#vanilla).

**`src/adaptableOptions.ts`**

```ts
import {AdaptableOptions} from '@adaptabletools/adaptable';
import {WebFramework} from './rowData';
import {turnOffTickingData} from './tickingDataHelper';

export const adaptableOptions: AdaptableOptions<WebFramework> = {
  primaryKey: 'id',
  adaptableId: 'Observable Condition Stale',
  expressionOptions: {
    liveRefreshIntervalMs: 1000,
  },
  dashboardOptions: {
    customToolbars: [
      {
        name: 'tickingToolbar',
        title: 'Ticking',
        toolbarButtons: [
          {
            label: 'Turn off Ticking Data',
            onClick: () => {
              turnOffTickingData();
            },
            buttonStyle: {
              tone: 'accent',
              variant: 'raised',
            },
          },
        ],
      },
    ],
  },
  initialState: {
    Dashboard: {
      ModuleButtons: ['FormatColumn'],
      Tabs: [
        {
          Name: 'Toolbars',
          Toolbars: ['FormatColumn', 'tickingToolbar'],
        },
      ],
    },
    Theme: {CurrentTheme: 'dark'},
    FormatColumn: {
      FormatColumns: [
        {
          Name: 'stale-github-stars',
          Scope: {
            ColumnIds: ['github_stars'],
          },
          Rule: 'NO_CHANGES{[github_stars], WITHIN(5s)}',
          Style: {
            BackColor: '#e0e0e0',
            ForeColor: '#757575',
          },
        },
      ],
    },
    Layout: {
      CurrentLayout: 'Standard Layout',
      Layouts: [
        {
          Name: 'Standard Layout',
          TableColumns: [
            'name',
            'github_stars',
            'language',
            'github_watchers',
            'open_issues_count',
            'license',
          ],
          AutoSizeColumns: true,
        },
      ],
    },
  },
};
```

**`src/onAdaptableReady.ts`**

```ts
import {AdaptableReadyInfo} from '@adaptabletools/adaptable';
import {tickNumericData} from './tickingDataHelper';

export const onAdaptableReady = ({adaptableApi}: AdaptableReadyInfo) => {
  tickNumericData(adaptableApi, 1000, ['github_stars']);
};
```

## Busy cells

Another common use case is to style a cell when it has moved **enough** within a sliding window.

When this happens, small ticks stay quiet until the net move crosses the threshold.

**Example: Observable Condition: Busy Cells**

Highlight Github Stars after a large net move

- Format Column Rule: `NET_CHANGE{[github_stars], WITHIN(30s)} > 20`
- Only `Github Stars` ticks (every 500ms by ±10)
- The style appears once the cumulative move in the last 30 seconds exceeds 20

Demo project (Vanilla); the files without a marker are shown below:

```text
src/
  adaptableOptions.ts
  agGridModules.ts      [template]
  columnDefs.ts         [template]
  gridOptions.ts        [template]
  index.ts              [template]
  onAdaptableReady.ts
  rowData.ts            [template]
  styles.css            [template]
  tickingDataHelper.ts  [template]
index.html              [template]
package.json            [template]
tsconfig.json           [template]
```

Files marked `[template]` are the same in every demo; see the [demo template](https://www.adaptabletools.com/llms/demo-template.md#vanilla).

**`src/adaptableOptions.ts`**

```ts
import {AdaptableOptions} from '@adaptabletools/adaptable';
import {WebFramework} from './rowData';

export const adaptableOptions: AdaptableOptions<WebFramework> = {
  primaryKey: 'id',
  adaptableId: 'Observable Condition Busy',
  expressionOptions: {
    liveRefreshIntervalMs: 1000,
  },
  initialState: {
    Dashboard: {
      ModuleButtons: ['FormatColumn'],
    },
    Theme: {CurrentTheme: 'dark'},
    FormatColumn: {
      FormatColumns: [
        {
          Name: 'busy-github-stars',
          Scope: {
            ColumnIds: ['github_stars'],
          },
          Rule: 'NET_CHANGE{[github_stars], WITHIN(30s)} > 20',
          Style: {
            BackColor: '#fff3cd',
            ForeColor: '#856404',
            FontWeight: 'Bold',
          },
        },
      ],
    },
    Layout: {
      CurrentLayout: 'Standard Layout',
      Layouts: [
        {
          Name: 'Standard Layout',
          TableColumns: [
            'name',
            'github_stars',
            'language',
            'github_watchers',
            'open_issues_count',
            'license',
          ],
          AutoSizeColumns: true,
        },
      ],
    },
  },
};
```

**`src/onAdaptableReady.ts`**

```ts
import {AdaptableReadyInfo} from '@adaptabletools/adaptable';
import {tickNumericData} from './tickingDataHelper';

export const onAdaptableReady = ({adaptableApi}: AdaptableReadyInfo) => {
  tickNumericData(adaptableApi, 500, ['github_stars']);
};
```
