# Default Layouts

Canonical page: https://www.adaptabletools.com/docs/handbook-layouts-default

- AdapTable can create a first-run Layout from AG Grid ColDefs when none are provided
- That Layout can optionally be rebuilt from ColDefs on every load
- Default Layout properties can be applied to all Layouts created at run-time
- State Options can extend all Layouts (new and existing) at design-time

AdapTable requires a Current Layout, and the vast majority of users ship one in [Initial Adaptable State](https://www.adaptabletools.com/docs/technical-reference-initial-state/index.md).

However sometimes this feels like overkill or unnecessary repitition.

For instance the Layout might be identical to properties already provided in AG Grid GridOptions and ColDefs.

Other users create multiple Layouts and want a way for the same base set of properties to exist on each.

While another use case wishes to easily patch Layouts that have been created.

AdapTable provides a solution for each of these use cases by allowing developers to:

- define a first-run Layout from AG Grid ColDefs and GridOptions
- apply default properties to be added to all Layouts created at runtime
- patch Layouts as they load

## Auto-creating Default Layout

Developers can ask AdapTable to create a default Layout in place of providing one themselves.

This is particularly useful if the Layout will be identical to the properties provided in ColDefs and GridOptions

This is configured using the `autoCreateLayout` property in [Layout Options](https://www.adaptabletools.com/docs/technical-reference-layouts/index.md).

- Developers have the option to provide a custom name for the default Layout
- If no name is provided, then the Layout is named "Default Layout"

AdapTable will create a new Layout using 2 sets of AG Grid properties:

- `columnDefs` - Order, Visibility, Sizing, Pinning, Sorts, Row Grouping, Pivoting and Aggregations
- `gridOptions` - `defaultColDef`, Pivot Mode, Row Model

- Any [Default Creation Properties](https://www.adaptabletools.com/docs/handbook-layouts-default/index.md#default-creation-properties) which have been provided are also applied when creating the default Layout
- ColDef values win when both set same field

AdapTable will only create a Default Layout if there are no other Layouts provided in State (unless the `createEveryLoad` property is set - see [below](#recreate-every-grid-load)).

If `autoCreateLayout` is set to *true*, but other Layouts are in Initial or Persisted State, no Default Layout is created

### `autoCreateLayout`

Create a first-run Layout from AG Grid ColDefs (when no Layouts are provided)

  `boolean | AutoCreateLayoutOptions`

When no Layouts exist, AdapTable can build one from ColDefs, including visibility, order, sizing, pinning, sorts, row groups and aggregations.

The property is defined as follows:

```
autoCreateLayout?: boolean | AutoCreateLayoutOptions;
```

The [`AutoCreateLayoutOptions`](https://www.adaptabletools.com/docs/reference/autocreatelayoutoptions.md) object is defined as follows:

// PUT Api here when working - no point doing a temp table.

A few points to note:

- Table vs Pivot is taken from `pivotMode` in GridOptions (ColDef `pivot` / `pivotIndex` is not enough).
- Viewport grids stay as Table Layouts.

The object provides options to create a default Layout named "Default Layout":

```ts {3}
// simply create a Default Layout - with the name of 'Default Layout'
layoutOptions: {
  autoCreateLayout: true,
}
```

... or to provide a Name for the Layout:
```ts {3}
// create a Default Layout with the name of "Overview"
layoutOptions: {
  autoCreateLayout: { name: 'Overview' }
}
```

...or to set a Layout to be created on each load:
```ts {3}
// create a Default Layout with the name of "Grid" and recreate it on each load
layoutOptions: {
  autoCreateLayout: { name: 'Grid', createEveryLoad: true }
}
```

### Persisting

The auto-created Layout persists into AdapTable State like any other Layout or other AdapTable object.

The Layout will then load with changes the next time AdapTable opens and it is treated like any other object.

- The exception to this rule is if the Layout is configured to re-create on every load (see below)
- When this happens the Layout is still persisted, but the next load will re-create the Layout, overriding any changes

**Example: Auto-create Layout**

Creating a first-run Layout from AG Grid ColDefs

- This example sets `autoCreateLayout: true` and provides **no** Layout in Initial State
- AdapTable builds a `Default Layout` from the ColDefs:
  - `Name` is pinned left and sorted ascending
  - `License` and `Description` are hidden (`hide: true`)
  - `Id` is hidden

- Open the Layout Toolbar and note the current Layout is named `Default Layout`
- Show `License` or `Description` from the Columns Tool Panel — they sit in ColDef order

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

```text
src/
  adaptableOptions.ts
  agGridModules.ts     [template]
  columnDefs.ts
  gridOptions.ts       [template]
  index.ts             [template]
  onAdaptableReady.ts  [template]
  rowData.ts           [template]
  styles.css           [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: 'Auto Create Layout',
  layoutOptions: {
    autoCreateLayout: true,
  },
  initialState: {
    Dashboard: {
      ModuleButtons: ['Layout'],
      PinnedToolbars: ['Layout'],
    },
    StatusBar: {
      StatusBars: [
        {
          Key: 'Center Panel',
          StatusBarPanels: ['Layout'],
        },
      ],
    },
    Theme: {CurrentTheme: 'dark'},
  },
};
```

**`src/columnDefs.ts`**

```ts
import {ColDef} from 'ag-grid-enterprise';
import {WebFramework} from './rowData';

export const columnDefs: ColDef<WebFramework>[] = [
  {
    field: 'name',
    cellDataType: 'text',
    sortable: true,
    pinned: 'left',
    sort: 'asc',
  },
  {
    field: 'language',
    cellDataType: 'text',
    enablePivot: true,
    enableRowGroup: true,
  },
  {
    field: 'github_stars',
    headerName: 'GitHub Stars',
    cellDataType: 'number',
    enableValue: true,
  },
  {
    field: 'github_watchers',
    headerName: 'GitHub Watchers',
    cellDataType: 'number',
    enableValue: true,
  },
  {
    field: 'license',
    cellDataType: 'text',
    hide: true,
    enablePivot: true,
    enableRowGroup: true,
  },
  {
    field: 'description',
    cellDataType: 'text',
    hide: true,
    sortable: false,
  },
  {
    field: 'open_issues_count',
    headerName: 'Open Issues',
    cellDataType: 'number',
    enableValue: true,
  },
  {
    field: 'open_pr_count',
    headerName: 'Open PRs',
    cellDataType: 'number',
    enableValue: true,
  },
  {
    field: 'id',
    cellDataType: 'number',
    hide: true,
    editable: false,
  },
];
```

### Row Grouping & Aggregations

The auto-created default Layout can include [Row Grouping](https://www.adaptabletools.com/docs/handbook-grouping-rows/index.md) and [Aggregations](https://www.adaptabletools.com/docs/handbook-aggregation/index.md) if they are provided in the AG Grid definitions.

**Example: Auto-create Grouped Layout**

Creating a first-run Layout with Row Grouping and Aggregations from ColDefs

- This example shows how to create a Default Layout that includes [Row Groups](https://www.adaptabletools.com/docs/handbook-grouping-rows/index.md) and [Aggregations](https://www.adaptabletools.com/docs/handbook-aggregation/index.md)
- The ColDefs group by `Language` (`rowGroup: true`) and aggregate:
  - `Github Stars` — `sum`
  - `Github Watchers` — `sum`
  - `Open Issues` — `avg`

- Open the Layout Toolbar and note the current Layout is named `Default Layout`
- The Columns Tool Panel shows `Language` in Row Groups and the three value columns

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

```text
src/
  adaptableOptions.ts
  agGridModules.ts     [template]
  columnDefs.ts
  gridOptions.ts       [template]
  index.ts             [template]
  onAdaptableReady.ts
  rowData.ts           [template]
  styles.css           [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: 'Auto Create Grouped Layout',
  layoutOptions: {
    autoCreateLayout: true,
  },
  initialState: {
    Dashboard: {
      ModuleButtons: ['Layout'],
      PinnedToolbars: ['Layout'],
    },
    StatusBar: {
      StatusBars: [
        {
          Key: 'Center Panel',
          StatusBarPanels: ['Layout'],
        },
      ],
    },
    Theme: {CurrentTheme: 'dark'},
  },
};
```

**`src/columnDefs.ts`**

```ts
import {ColDef} from 'ag-grid-enterprise';
import {WebFramework} from './rowData';

export const columnDefs: ColDef<WebFramework>[] = [
  {
    field: 'name',
    cellDataType: 'text',
    sortable: true,
  },
  {
    field: 'language',
    cellDataType: 'text',
    rowGroup: true,
    enableRowGroup: true,
  },
  {
    field: 'github_stars',
    headerName: 'GitHub Stars',
    cellDataType: 'number',
    aggFunc: 'sum',
    enableValue: true,
  },
  {
    field: 'github_watchers',
    headerName: 'GitHub Watchers',
    cellDataType: 'number',
    aggFunc: 'sum',
    enableValue: true,
  },
  {
    field: 'open_issues_count',
    headerName: 'Open Issues',
    cellDataType: 'number',
    aggFunc: 'avg',
    enableValue: true,
  },
  {
    field: 'license',
    cellDataType: 'text',
    enableRowGroup: true,
  },
  {
    field: 'id',
    cellDataType: 'number',
    hide: true,
    editable: false,
  },
];
```

**`src/onAdaptableReady.ts`**

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

export const onAdaptableReady = ({agGridApi}: AdaptableReadyInfo) => {
  agGridApi.openToolPanel('columns');
  agGridApi.expandAll();
};
```

### Pivot Layouts

The auto-created default Layout can be a [Pivot Layout](https://www.adaptabletools.com/docs/handbook-layouts-pivot/index.md) (rather than a Table Layout).

- A Pivot Layout is created only when `pivotMode` in GridOptions is set to *true*
- Setting `pivot` or `pivotIndex` on ColDefs is not enough — without `pivotMode` AdapTable creates a Table Layout

**Example: Auto-create Pivot Layout**

Creating a first-run Pivot Layout from ColDefs

- This example shows how to create a [Pivot](https://www.adaptabletools.com/docs/handbook-layouts-pivot/index.md) `Default Layout` with Pivot Columns, Grouped Rows and Aggregations
- `pivotMode` is set to *true* in GridOptions — that is what makes this a Pivot Layout
- The ColDefs then supply the Pivot contents:
  - `License` is a pivot column (`pivot: true`)
  - `Language` is row-grouped (`rowGroup: true`)
  - `Github Stars` and `Github Watchers` are summed

- Open the Layout Toolbar and note the current Layout is a Pivot Layout named `Default Layout`
- The Columns Tool Panel shows `Language` in Row Groups, `License` in Pivot and the two value columns

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

```text
src/
  adaptableOptions.ts
  agGridModules.ts     [template]
  columnDefs.ts
  gridOptions.ts
  index.ts             [template]
  onAdaptableReady.ts
  rowData.ts           [template]
  styles.css           [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: 'Auto Create Pivot Layout',
  layoutOptions: {
    autoCreateLayout: true,
  },
  initialState: {
    Dashboard: {
      ModuleButtons: ['Layout'],
      PinnedToolbars: ['Layout'],
    },
    StatusBar: {
      StatusBars: [
        {
          Key: 'Center Panel',
          StatusBarPanels: ['Layout'],
        },
      ],
    },
    Theme: {CurrentTheme: 'dark'},
  },
};
```

**`src/columnDefs.ts`**

```ts
import {ColDef} from 'ag-grid-enterprise';
import {WebFramework} from './rowData';

export const columnDefs: ColDef<WebFramework>[] = [
  {
    field: 'name',
    cellDataType: 'text',
    sortable: true,
  },
  {
    field: 'language',
    cellDataType: 'text',
    rowGroup: true,
    enableRowGroup: true,
  },
  {
    field: 'license',
    cellDataType: 'text',
    pivot: true,
    enablePivot: true,
  },
  {
    field: 'github_stars',
    headerName: 'GitHub Stars',
    cellDataType: 'number',
    aggFunc: 'sum',
    enableValue: true,
  },
  {
    field: 'github_watchers',
    headerName: 'GitHub Watchers',
    cellDataType: 'number',
    aggFunc: 'sum',
    enableValue: true,
  },
  {
    field: 'id',
    cellDataType: 'number',
    hide: true,
    editable: false,
  },
];
```

**`src/gridOptions.ts`**

```ts
import {GridOptions, themeBalham} from 'ag-grid-enterprise';

import {rowData, WebFramework} from './rowData';
import {columnDefs} from './columnDefs';

export const gridOptions: GridOptions<WebFramework> = {
  theme: themeBalham,
  defaultColDef: {
    resizable: true,
    sortable: true,
    editable: true,
    filter: true,
    floatingFilter: true,
  },
  columnDefs: columnDefs,
  rowData: rowData,
  pivotMode: true,
  sideBar: true,
  suppressMenuHide: true,
  columnMenu: 'new',
  cellSelection: true,
  statusBar: {
    statusPanels: [
      {statusPanel: 'agTotalRowCountComponent', align: 'left'},
      {statusPanel: 'agFilteredRowCountComponent'},
      {
        key: 'Center Panel',
        statusPanel: 'AdaptableStatusPanel',
        align: 'center',
      },
    ],
  },
};
```

**`src/onAdaptableReady.ts`**

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

export const onAdaptableReady = ({agGridApi}: AdaptableReadyInfo) => {
  agGridApi.openToolPanel('columns');
  agGridApi.expandAll();
};
```

### Recreate Every Grid Load

The Default Layout can be configured to be created **every time** AdapTable loads.

This is done by setting `createEveryLoad` to _true_ in `autoCreateLayout`.

```
autoCreateLayout: { name: 'Overview', createEveryLoad: true }
```

When this happens, changes made to the Layout in the previous session (and persisted into State), are ignored.

If other Layouts exist but the named Layout is still present, that named Layout is recreated; the other Layouts are left unchanged.

If `name` is omitted, `createEveryLoad` still targets `Default Layout`.

If the named Layout was deleted and other Layouts are present in State, the default Layout is not auto-created

**Example: Rebuild Layout Every Load**

Replacing a named Layout from ColDefs on every load

- This example sets `autoCreateLayout: { name: 'Overview', createEveryLoad: true }`
- A persisted `Overview` Layout is loaded with only `Name` and `Language` visible
- Because `createEveryLoad` is *true*, that Layout is replaced from ColDefs on load — so all ColDef columns appear
- Default creation properties also add a [Column Filter](https://www.adaptabletools.com/docs/handbook-column-filter/index.md) on `Language`
- The `Reload Layout` button in the custom Toolbar restores that same ColDef snapshot — the same thing `createEveryLoad` does on the next load

- Hide a column, change the sort, or clear the `Language` filter
- Click `Reload Layout` in the Buttons Toolbar — those changes are discarded and the ColDef Layout (plus the TypeScript filter) is shown again

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]
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 {
  AdaptableButton,
  AdaptableOptions,
  CustomToolbarButtonContext,
} from '@adaptabletools/adaptable';
import {WebFramework} from './rowData';
import {getColDefLayout} from './onAdaptableReady';

export const adaptableOptions: AdaptableOptions<WebFramework> = {
  primaryKey: 'id',
  adaptableId: 'Auto Create Layout Every Load',
  layoutOptions: {
    autoCreateLayout: {
      name: 'Overview',
      createEveryLoad: true,
    },
    layoutCreationDefaultProperties: {
      tableLayout: {
        ColumnFilters: [
          {
            ColumnId: 'language',
            Expression: '[language] = "TypeScript"',
          },
        ],
      },
    },
  },
  dashboardOptions: {
    customToolbars: [
      {
        name: 'ButtonToolbar',
        title: 'Buttons',
        toolbarButtons: [
          {
            label: 'Reload Layout',
            buttonStyle: {
              tone: 'accent',
              variant: 'outlined',
            },
            onClick: (
              _button: AdaptableButton<CustomToolbarButtonContext>,
              context: CustomToolbarButtonContext
            ) => {
              const snapshot = getColDefLayout();
              if (!snapshot) {
                return;
              }
              const existing = context.adaptableApi.layoutApi.getLayoutByName(
                snapshot.Name
              );
              context.adaptableApi.layoutApi.createOrUpdateLayout({
                ...structuredClone(snapshot),
                Uuid: existing?.Uuid ?? snapshot.Uuid,
              });
              context.adaptableApi.layoutApi.setLayout(snapshot.Name);
            },
          },
        ],
      },
    ],
  },
  stateOptions: {
    loadState: () =>
      Promise.resolve({
        Layout: {
          CurrentLayout: 'Overview',
          Layouts: [
            {
              Name: 'Overview',
              TableColumns: ['name', 'language'],
            },
          ],
        },
      }),
  },
  initialState: {
    Dashboard: {
      ModuleButtons: ['Layout'],
      Tabs: [
        {
          Name: 'Default',
          Toolbars: ['ButtonToolbar', 'Layout'],
        },
      ],
    },
    StatusBar: {
      StatusBars: [
        {
          Key: 'Center Panel',
          StatusBarPanels: ['Layout'],
        },
      ],
    },
    Theme: {CurrentTheme: 'dark'},
  },
};
```

**`src/onAdaptableReady.ts`**

```ts
import {AdaptableReadyInfo, Layout} from '@adaptabletools/adaptable';

let colDefLayout: Layout | undefined;

export function getColDefLayout(): Layout | undefined {
  return colDefLayout;
}

export const onAdaptableReady = ({adaptableApi}: AdaptableReadyInfo) => {
  colDefLayout = structuredClone(adaptableApi.layoutApi.getCurrentLayout());
};
```

## Default Creation Properties

Default creation properties are applied automatically to all new Table and Pivot Layouts **created at runtime**.

These properties ensure consistency across newly created Layouts without requiring manual configuration.

- Layouts created through [Layout API](https://www.adaptabletools.com/docs/technical-reference-layouts/index.md) will contain these properties (unless property is explicitly overridden)
- Layouts created via the UI wil show these properties in [Layout Wizard](https://www.adaptabletools.com/docs/handbook-layouts-wizard-table/index.md) (allowing user to change them)
- Layouts created by `autoCreateLayout` also receive these properties (ColDef values win when both set same field)

This is done using the `layoutCreationDefaultProperties` property in [Layout Options](https://www.adaptabletools.com/docs/technical-reference-layouts/index.md).

### `layoutCreationDefaultProperties`

Sets default properties for new Layouts (Table or Pivot)

  [`DefaultLayoutProperties`](https://www.adaptabletools.com/docs/reference/layoutcreationdefaultproperties.md)

Provides a set of Default Properties for new Layouts (Table or Pivot).

The definition of the property is as follows:

```
layoutCreationDefaultProperties?:
    | LayoutCreationDefaultProperties
    | ((
        context: LayoutCreationDefaultPropertiesContext
      ) => TableLayoutCreationDefaultProperties | PivotLayoutCreationDefaultProperties);
```

As can be seen, the default properties can be provided as an object or via a function.

<b>Providing an Object</b>

It is possible to return a [`LayoutCreationDefaultProperties`](https://www.adaptabletools.com/docs/reference/layoutcreationdefaultproperties.md) which contains default properties for Table and Pivot Layouts:

| Property | Type | Description |
| --- | --- | --- |
| [pivotLayout](https://www.adaptabletools.com/docs/reference/layoutcreationdefaultproperties.md#pivotlayout) | [`PivotLayoutCreationDefaultProperties`](https://www.adaptabletools.com/docs/reference/pivotlayoutcreationdefaultproperties.md) | Default properties to apply when creating a new Pivot Layout |
| [tableLayout](https://www.adaptabletools.com/docs/reference/layoutcreationdefaultproperties.md#tablelayout) | [`TableLayoutCreationDefaultProperties`](https://www.adaptabletools.com/docs/reference/tablelayoutcreationdefaultproperties.md) | Default properties to apply when creating a new Table Layout |

```ts {4,12}
// Provide default properties to be used im Table
layoutOptions: {
  layoutCreationDefaultProperties: {
    tableLayout: {
      ColumnSorts: [
        {
          ColumnId: 'name',
          SortOrder: 'Asc',
        },
      ],
    },
    pivotLayout: {
      PivotAggregationColumns: [
        {
          ColumnId: 'github_stars',
          AggFunc: 'sum',
        },
        {
          ColumnId: 'github_watchers',
          AggFunc: 'sum',
        },
      ],
    },
  },
},
```

<b>Using a Function</b>

Alternatively you can provide a function which will return the object on a per-case basis.

The function receives [`LayoutCreationDefaultPropertiesContext`](https://www.adaptabletools.com/docs/reference/layoutcreationdefaultpropertiescontext.md) which is defined as follows:

| Property | Type | Description |
| --- | --- | --- |
| [layoutType](https://www.adaptabletools.com/docs/reference/layoutcreationdefaultpropertiescontext.md#layouttype) | `'table' \| 'pivot'` | Type of Layout (&#39;table&#39; \| &#39;pivot&#39;) |
| [adaptableContext](https://www.adaptabletools.com/docs/reference/layoutcreationdefaultpropertiescontext.md#adaptablecontext) | `any` | Custom application Context provided in `AdaptableOptions.adaptableContext` |

When using the function you return one of 2 objects:

- [`DefaultTableLayoutProperties`](https://www.adaptabletools.com/docs/reference/tablelayoutcreationdefaultproperties.md) - set of Table Layout properties
- [`DefaultPivotLayoutProperties`](https://www.adaptabletools.com/docs/reference/pivotlayoutcreationdefaultproperties.md) - set of Pivot Layout properties

Neither of these objects allow you to provide a default `Name` property (since that has to be unique to the Layout)

```

  layoutOptions: {
    layoutCreationDefaultProperties: (context: LayoutCreationDefaultPropertiesContext) => {
      if (context.layoutType == 'table') {
        return {
          ColumnSorts: [
            {
              ColumnId: 'name',
              SortOrder: 'Asc',
            },
          ],
        };
      } else {
        return {
          PivotAggregationColumns: [
            {
              ColumnId: 'github_stars',
              AggFunc: 'sum',
            },
            {
              ColumnId: 'github_watchers',
              AggFunc: 'sum',
            },
          ],
        };
      }
    },
  },
```

**Example: Default Creation Props**

Providing Default Creation Props in Layout Options

- In this example we have provided default creation properties for both Table and Pivot Layouts:
  - For Table Layouts - we default a on `Name` Column, and a [Column Filter](https://www.adaptabletools.com/docs/handbook-column-filter/index.md) on `Language` Column
  - For Pivot Layouts - we default [Aggregations](https://www.adaptabletools.com/docs/handbook-aggregation/index.md) on `Github Stars` and `Github Watchers` Columns (suppressing the Agg Func), a [GrandTotalRow](https://www.adaptabletools.com/docs/handbook-aggregation-grand-total-row/index.md) at bottom and a [PivotGrandTotal](https://www.adaptabletools.com/docs/handbook-layouts-pivot-total-columns/index.md) Column before

- In the Layout Toolbar click to add a new Table Layout and note that the new Layout already contains the Column Sort and Column Filter defined in default props
- Then click to add a new Pivot Layout and note that the new Layout already contains the Aggregations, GrandTotalRow and PivotGrand Total Column

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  [template]
  rowData.ts           [template]
  styles.css           [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,
  LayoutCreationDefaultPropertiesContext,
} from '@adaptabletools/adaptable';
import {WebFramework} from './rowData';

export const adaptableOptions: AdaptableOptions<WebFramework> = {
  primaryKey: 'id',
  adaptableId: 'Default Layout Props',
  layoutOptions: {
    layoutCreationDefaultProperties: (
      context: LayoutCreationDefaultPropertiesContext
    ) => {
      if (context.layoutType == 'table') {
        return {
          ColumnSorts: [
            {
              ColumnId: 'name',
              SortOrder: 'Asc',
            },
          ],
          ColumnFilters: [
            {
              ColumnId: 'language',
              Expression: '[language] = "TypeScript"',
            },
          ],
          AutoSizeColumns: true,
        };
      } else {
        return {
          PivotAggregationColumns: [
            {
              ColumnId: 'github_stars',
              AggFunc: 'sum',
            },
            {
              ColumnId: 'github_watchers',
              AggFunc: 'sum',
            },
          ],
          SuppressAggFuncInHeader: true,
          GrandTotalRow: 'bottom',
          PivotGrandTotal: 'before',
        };
      }
    },
  },
  initialState: {
    Dashboard: {
      ModuleButtons: ['Layout'],
      PinnedToolbars: ['Layout'],
    },
    StatusBar: {
      StatusBars: [
        {
          Key: 'Center Panel',
          StatusBarPanels: ['Layout'],
        },
      ],
    },
    Theme: {CurrentTheme: 'dark'},
    Layout: {
      CurrentLayout: 'Table Layout',
      Layouts: [
        {
          TableColumns: [
            'name',
            'license',
            'language',
            'github_stars',
            'open_pr_count',
            'closed_issues_count',
            'created_at',
            'updated_at',
            'pushed_at',
            'created_at',
            'has_wiki',
            'github_watchers',
            'description',
            'open_issues_count',
            'closed_pr_count',
            'has_projects',
            'has_pages',
            'week_issue_change',
          ],
          Name: 'Table Layout',
          AutoSizeColumns: true,
        },
      ],
    },
  },
};
```

## Patching Initial State Layouts

AdapTable allows developers to enhance **all** Layouts (new and existing) by manipulating the Layout State.

This is most easily achieved by leveraging 2 [State Options](https://www.adaptabletools.com/docs/technical-reference-adaptable-state/index.md) functions:

- `applyState` - modifies the Layout state dynamically
- `saveState` - controls how Layouts are persisted to avoid polluting the saved state with default configurations

**Example: Default Layout Props**

Providing Default Layout Properties via State Functions

- This example demonstrates how to create default layout properties in Initial State; we:
    - Add a read-only `All Columns` Layout that includes all available columns with a default sort on `name`
    - Prevent the default `All Columns` Layout from being persisted by filtering it out in the `saveState` function in [State Options](https://www.adaptabletools.com/docs/technical-reference-adaptable-state/index.md)
    - Apply a default descending sort on the `github_stars` column to all Layouts that do not contain a sort

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  [template]
  rowData.ts           [template]
  styles.css           [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 {AdaptablePersistentState, Layout} from '@adaptabletools/adaptable';
import {AdaptableOptions, TableLayout} from '@adaptabletools/adaptable';
import {WebFramework} from './rowData';

export const adaptableOptions: AdaptableOptions<WebFramework> = {
  primaryKey: 'id',
  adaptableId: 'Default Layout Props',
  initialState: {
    Layout: {
      CurrentLayout: 'Custom Layout',
      Layouts: [
        {
          Name: 'Custom Layout',
          TableColumns: [
            'name',
            'license',
            'language',
            'description',
            'github_stars',
          ],
        },
      ],
    },
    Theme: {CurrentTheme: 'dark'},
    Dashboard: {
      ModuleButtons: ['Layout'],
      PinnedToolbars: ['Layout'],
    },
    StatusBar: {
      StatusBars: [
        {
          Key: 'Center Panel',
          StatusBarPanels: ['Layout'],
        },
      ],
    },
  },
  stateOptions: {
    applyState: (state, config) => {
      addAllColumnLayout(state);
      enhanceLayoutsWithDefaultSorting(state);
      return state;
    },
    saveState: (state, config) => {
      // remove the default layout before saving state
      // we don't want to pollute the persisted state with it
      state.Layout.Layouts = state.Layout.Layouts.filter(
        layout => layout.Metadata?.DEFAULT_PROP !== true
      ) as [Layout, ...Layout[]];
      return state;
    },
  },
};

function addAllColumnLayout(state: Partial<AdaptablePersistentState>) {
  const ALL_COLS_LAYOUT: TableLayout = {
    Metadata: {
      DEFAULT_PROP: true,
    },
    IsReadOnly: true,
    Name: 'All Columns',
    TableColumns: [
      'name',
      'license',
      'language',
      'github_stars',
      'open_pr_count',
      'closed_issues_count',
      'created_at',
      'updated_at',
      'pushed_at',
      'created_at',
      'has_wiki',
      'github_watchers',
      'description',
      'open_issues_count',
      'closed_pr_count',
      'has_projects',
      'has_pages',
      'week_issue_change',
    ],
    ColumnSorts: [{ColumnId: 'name', SortOrder: 'Asc'}],
  };

  state.Layout?.Layouts?.push(ALL_COLS_LAYOUT);
}

function enhanceLayoutsWithDefaultSorting(
  state: Partial<AdaptablePersistentState>
) {
  state.Layout?.Layouts?.forEach(layout => {
    if (layout.ColumnSorts?.length) {
      return;
    }
    layout.ColumnSorts = [{ColumnId: 'github_stars', SortOrder: 'Desc'}];
  });
}
```
