---
product: "AG Studio"
title: "Data Panel"
description: "Use AG Studio's Data Panel to browse data sources, tables and fields, see how sources relate, and find the calculated fields you can use in Widgets."
framework: react
version: "3.1.0"
related:
    - title: "Fields in Widgets"
      url: "https://www.ag-grid.com/studio/analysts/fields-in-widgets/"
    - title: "Calculations"
      url: "https://www.ag-grid.com/studio/analysts/calculations/"
    - title: "Formatting Values"
      url: "https://www.ag-grid.com/studio/analysts/formatting-values/"
    - title: "Blanks and Missing Values"
      url: "https://www.ag-grid.com/studio/analysts/blanks-and-missing-values/"
llms: "https://www.ag-grid.com/studio/llms.txt"
---

# Data Panel

The Data Panel organises the available data and shows how it is structured across sources.

AG Studio supports multiple data sources. This page explains how the Data Panel presents your data and how that data is structured across sources. For how fields behave in widgets, see [Fields in Widgets](https://www.ag-grid.com/studio/analysts/fields-in-widgets/).

## Data Panel

The Data Panel lists the data available to the report, grouped by source. For an overview of how the Data Panel fits within the Studio interface, see [User Interface](https://www.ag-grid.com/studio/analysts/user-interface/).

You can search the Data Panel for items by name. When you drag a data pill, the places you can drop it are highlighted in blue. You can drop data pills into widget configuration slots and [Filter Conditions](https://www.ag-grid.com/studio/analysts/filters-panel/).

Select any data item to switch the Compose Panel to its data-field view, which displays metadata about that item.

## Data Items

Data items are the fields listed in the Data Panel. Each field can be used in widgets and is one of three types: a column, a calculated column or a measure.

- Columns are fields that come directly from the underlying data source and are typically used for categories (grouping) and, where appropriate, as values.
- Calculated Columns are fields derived from other data that return a value for each row.
- Measures are pre-aggregated calculations intended for Metrics and KPIs.

Each data item has the following properties:

| Property | Description |
| --- | --- |
| ID | The unique identifier for the data item. |
| Name | The display name shown in the interface. |
| Description | Additional supporting information about the data item. |
| Data Type | The type of data the item contains, such as text, number, date, or boolean. |
| Calculation Type | Whether the field is calculated: No Calculation for a column from the source, Calculation for a Calculated Column, or Measure for a Measure. |
| Format | How the value is displayed in the interface, for example as text, currency, percentage, or a date format. |

Select any field in the Data Panel to open its data-field view, which shows the metadata for that field, including its name, description, data type, calculation type, and format.

Your developer configures ID, Name and Data Type, which are required, and Description and Format, which are optional.

Calculation Type shows which of the three kinds of field it is. This is chosen when the field is created, not worked out from the data. A field that comes from a data source is always a column, so it shows No Calculation. A calculation is either a Calculated Column or a Measure, and whoever creates it chooses which: your developer for the calculations you are given, and you for the ones you add yourself (see [Calculations](https://www.ag-grid.com/studio/analysts/calculations/)).

This choice decides how you can use the field. A column or a Calculated Column holds a value for each row, so when you use one as a value in a widget you choose how to aggregate it. A Measure is already aggregated, so it brings its own aggregation and no other can be applied to it. See [Aggregation](https://www.ag-grid.com/studio/analysts/fields-in-widgets/#aggregation).

In the example below, select a field in the Data Panel to see its properties. Most fields come straight from the Sales data, so their Calculation Type is No Calculation. Gross Amount is a Calculated Column and Average Sale is a Measure.

#### Data Field

```ts
import {
  AgExpressionFieldDefinition,
  AgFieldDefinition,
  AgReportState,
  AgStudioApi,
  AgStudioProperties,
  createStudio,
  enableStudioDevValidations,
} from "ag-studio";
import { getData } from "./data.ts";

if (process.env.NODE_ENV !== "production") {
  // Enable extended validations only for development
  enableStudioDevValidations();
}

const salesFields: AgFieldDefinition[] = [
  {
    id: "sale_id",
    name: "Sale ID",
    format: "textFormat",
    description: "Unique identifier for each sale transaction",
  },
  {
    id: "date",
    name: "Date",
    format: "dateFormat",
    description: "Date when the sale occurred",
  },
  {
    id: "store_id",
    name: "Store ID",
    format: "textFormat",
    description: "Identifier for the store where the sale took place",
  },
  {
    id: "product_id",
    name: "Product ID",
    format: "textFormat",
    description: "Identifier for the product sold",
  },
  {
    id: "customer_id",
    name: "Customer ID",
    format: "textFormat",
    description: "Identifier for the customer making the purchase",
  },
  {
    id: "employee_id",
    name: "Employee ID",
    format: "textFormat",
    description: "Identifier for the employee who processed the sale",
  },
  {
    id: "quantity",
    name: "Quantity",
    format: "integerFormat",
    description: "Number of units sold",
  },
  {
    id: "unit_price",
    name: "Unit Price",
    format: "currencyFormat",
    description: "Price per unit of the product",
    formatOptions: {
      format: "$#,##0.00",
    },
  },
  {
    id: "discount_pct",
    name: "Discount Percentage",
    format: "percentageFormat",
    description: "Discount applied to the sale as a percentage",
    formatOptions: {
      format: "0.00%",
    },
  },
  {
    id: "amount",
    name: "Amount",
    format: "currencyFormat",
    description: "Total sale amount after discounts",
    formatOptions: {
      format: "$#,##0.00",
    },
  },
  {
    id: "payment_method",
    name: "Payment Method",
    format: "textFormat",
    description: "Method used for payment",
  },
  {
    id: "status",
    name: "Status",
    format: "textFormat",
    description: "Current status of the sale transaction",
  },
  {
    id: "promo_id",
    name: "Promo ID",
    format: "textFormat",
    description: "Identifier for any promotional offer applied",
  },
];

// A Calculated Column, worked out for each row, and a Measure, which is already aggregated
const salesCalculations: AgExpressionFieldDefinition[] = [
  {
    id: "gross_amount",
    name: "Gross Amount",
    description: "Quantity multiplied by unit price, before discounts",
    isMeasure: false,
    format: "currencyFormat",
    formatOptions: {
      format: "$#,##0.00",
    },
    expression: {
      operator: "multiply",
      inputs: [{ id: "sales.quantity" }, { id: "sales.unit_price" }],
    },
  },
  {
    id: "average_sale",
    name: "Average Sale",
    description: "Total sale amount divided by the number of sales",
    isMeasure: true,
    format: "currencyFormat",
    formatOptions: {
      format: "$#,##0.00",
    },
    expression: {
      operator: "divide",
      inputs: [
        { id: "sales.amount", aggregation: "sum" },
        { id: "sales.sale_id", aggregation: "countd" },
      ],
    },
  },
];

const initialState: AgReportState = {
  pages: [
    {
      id: "a",
    },
  ],
  selectedPageId: "a",
};

const studioProperties: AgStudioProperties = {
  mode: "edit",
  initialState,
  panels: {
    edit: {
      right: ["edit", "data"],
    },
  },
  data: {
    sources: [
      {
        id: "sales",
        name: "Sales",
        fields: salesFields,
        data: getData(),
      },
    ],
    expressions: salesCalculations,
  },
};

let studioApi: AgStudioApi;

// setup Studio after the page has finished loading
const studioDiv = document.querySelector<HTMLElement>("#myStudio")!;
studioApi = createStudio(studioDiv, studioProperties);
```

[Live example: Data Field](https://www.ag-grid.com/studio/examples/data-panel/data-field/typescript/)

## Data Source

The Data Panel groups data items by data source. A report can use one data source or several.

When a report uses a single data source, all fields and calculations come from that source, so you can set up Widgets without thinking about relationships.

When a report uses several data sources, every data item is listed under the source it comes from. Each calculation is also listed under a single source, even when its expression reads from more than one:

- A calculation you create stays in the section you created it in, whatever its expression later references.
- A calculation your developer provides is listed under the first source its expression reaches, whether it names that source itself or reaches it through another calculation it references. If it reaches no source at all, it is listed in a Computed Columns section at the end of the panel.

If the data sources are related, you can combine data items from different sources when [Configuring Widgets](https://www.ag-grid.com/studio/analysts/building-widgets/#widget-setup). If the data you select is not related, the interface prevents invalid combinations.

In the example below, the table widget combines data items from two sources: product names from the Products table, and order metrics from the Order Items table, including quantity, unit price and net sales.

#### Multi-Data Source

```ts
import {
  AgReportState,
  AgStudioApi,
  AgStudioProperties,
  createStudio,
  enableStudioDevValidations,
} from "ag-studio";
import { getMainDemoData } from "./data.ts";

if (process.env.NODE_ENV !== "production") {
  // Enable extended validations only for development
  enableStudioDevValidations();
}

const initialState: AgReportState = {
  pages: [
    {
      id: "page1",
      widgets: {
        "1": {
          type: "grid",
          dataMapping: {
            cols: [
              { id: "products.product_name" },
              { id: "order_items.quantity", aggregation: "sum" },
              { id: "order_items.unit_price", aggregation: "avg" },
              { id: "net_sales" },
            ],
          },
          format: {
            title: {
              enabled: true,
              text: "Sales by Product",
            },
          },
        },
      },
      widgetLayout: {
        "1": {
          xTrack: 0,
          yTrack: 0,
          xSpan: 24,
          ySpan: 32,
        },
      },
    },
  ],
  selectedPageId: "page1",
};

const studioProperties: AgStudioProperties = {
  mode: "edit",
  initialState,
  panels: {
    edit: {
      right: ["edit", "data"],
    },
  },
  data: getMainDemoData("https://www.ag-grid.com/studio/example-assets"),
};

let studioApi: AgStudioApi;

// setup Studio after the page has finished loading
const studioDiv = document.querySelector<HTMLElement>("#myStudio")!;
studioApi = createStudio(studioDiv, studioProperties);
```

[Live example: Multi-Data Source](https://www.ag-grid.com/studio/examples/data-panel/multi-data-source/typescript/)

### Fields from Multiple Tables

In some data models, combining fields from certain tables counts some rows more than once. The Widget then shows totals that look plausible but are too large.

For example, if each order item can carry several tags, grouping Net Sales by tag counts each order item once for every tag it carries.

Some combinations are safe:

- A Widget with no grouping, such as a KPI showing one total, is not affected.
- Values from two tables that both relate to a shared table can go in the same Widget, as long as you group by a field from the shared table. For example, order item sales and shipment counts can be shown together by product, when both tables relate to Products.

If a total looks higher than you expect, check with your developer. They can set the report to refuse combinations that would inflate totals, instead of showing them.

## Calculated Fields

Some fields in the Data Panel are calculations rather than raw source columns. Calculations are derived from other fields, and are either provided by your developer or created by you (see [Calculations](https://www.ag-grid.com/studio/analysts/calculations/)). They are worked out as the report runs rather than stored in the underlying data, so they update as the data changes. There are two types of calculation:

Calculated Columns are non-aggregated calculations that return a value for each row. They are useful for transforming data, such as cleaning up labels, grouping values into bands, or setting flags based on logic.

Measures are pre-aggregated calculations that work out values for the whole dataset or per category. Used without any grouping categories, a Measure returns a single aggregated value for the entire dataset, such as total revenue across all regions. Used with categories, it returns one value per category, such as total revenue per region. Measures are intended for Metrics and KPIs, and you cannot change their aggregation.

Both are derived from other fields and worked out as the report runs. The difference is whether the value arrives already aggregated. A Calculated Column's value does not, so it behaves like any other column in a widget and you choose how to aggregate it. A Measure's value does, so it carries its own aggregation and you cannot apply another on top.

| Icon | Description |
| --- | --- |
| ![Number data type](https://www.ag-grid.com/studio/_astro/field-number.CEW-si33.svg) | Number data types |
| ![Calculated number data type](https://www.ag-grid.com/studio/_astro/field-number-calculated.C7Vr8OAR.svg) | Calculated number data type |

In the example below, the table shows a measure grouped by product. Line Net (sum) is an aggregated column calculated from order items, and Gross Margin % is a measure that shows the aggregated margin percentage for each product.

#### Calculations

```ts
import {
  AgReportState,
  AgStudioApi,
  AgStudioProperties,
  createStudio,
  enableStudioDevValidations,
} from "ag-studio";
import { getCalculationsData } from "./data.ts";

if (process.env.NODE_ENV !== "production") {
  // Enable extended validations only for development
  enableStudioDevValidations();
}

const initialState: AgReportState = {
  pages: [
    {
      id: "page1",
      widgets: {
        "1": {
          type: "grid",
          dataMapping: {
            cols: [
              { id: "products.product_name" },
              { id: "line_net", aggregation: "sum" },
              { id: "gross_margin_pct" },
            ],
          },
          format: {
            title: {
              enabled: true,
              text: "Calculated Column and Measure by Product",
            },
          },
        },
      },
      widgetLayout: {
        "1": {
          xTrack: 0,
          yTrack: 0,
          xSpan: 24,
          ySpan: 32,
        },
      },
    },
  ],
  selectedPageId: "page1",
};

const studioProperties: AgStudioProperties = {
  mode: "edit",
  initialState,
  panels: {
    edit: {
      right: ["edit", "data"],
    },
  },
  data: getCalculationsData("https://www.ag-grid.com/studio/example-assets"),
};

let studioApi: AgStudioApi;

// setup Studio after the page has finished loading
const studioDiv = document.querySelector<HTMLElement>("#myStudio")!;
studioApi = createStudio(studioDiv, studioProperties);
```

[Live example: Calculations](https://www.ag-grid.com/studio/examples/data-panel/calculations-example/typescript/)
