# GridView

The **GridView** widget is a layout widget designed for displaying items in a scrollable, two-dimensional grid. It's perfect for photo galleries, product catalogs, dashboards, and any interface that requires items to be arranged in rows and columns.

{% embed url="<https://www.youtube.com/watch?v=jP0gh2qO3oI>" %}

Watch this on Youtube - <https://www.youtube.com/watch?v=jP0gh2qO3oI>

Unlike ListView, which displays items in a single direction, GridView arranges items both horizontally and vertically, creating a table-like structure.

{% hint style="info" %}
The GridView widget works exactly like Flutter's `GridView.builder`. For an in-depth technical understanding, you can refer to the official Flutter GridView documentation.
{% endhint %}

### Use Cases

Use **GridView** when you want to display items in a **grid layout** (rows + columns), instead of a single vertical list.

You’ll typically use **GridView** for:

* **Product & Catalog Grids**
  * E-commerce product cards
  * Category tiles (Men, Women, Electronics, etc.)
* **Image & Media Galleries**
  * Photo grids
  * Video thumbnails
  * Story/highlight tiles
* **Icon / Feature Menus**
  * “App launcher” style icons
  * Feature shortcuts on a dashboard (Orders, Wallet, Offers…)
* **Compact, Visual Collections**
  * Tags, cards, or any repeated visual item where grid makes better use of screen space than a list.

### Core Concepts

#### 1. Dynamic Children Only

The GridView widget **requires** a data source to function. You cannot add static children individually in the builder. Instead, you provide a `JsonArray` of data, and GridView automatically repeats a single child widget template for each item in that array.

This is fundamentally the same as ListView—GridView is purpose-built for data-driven grids and uses lazy rendering to efficiently display large datasets.

{% hint style="info" %}
**Note:** If you need a fixed grid layout with specific, hand-placed widgets (like a dashboard), use a **Column** with **Row** widgets inside, or use **Wrap** widget instead. GridView is designed exclusively for dynamic, data-driven content.
{% endhint %}

#### 2. Grid Structure: Rows & Columns

GridView arranges items in a grid defined by:

* **Cross Axis (Columns)**: The number of items per row, controlled by `Cross Axis Count`.
* **Main Axis (Rows)**: The vertical flow direction. Items wrap to a new row when the cross axis count is reached.

For example, with `Cross Axis Count: 3`, items are arranged in rows of 3 columns each.

#### 3. Lazy Building & Performance

When using a data source, GridView uses **lazy rendering**—it only builds grid items as they scroll into view. This makes it highly performant for displaying hundreds or thousands of items without impacting app performance.

{% hint style="success" %}
**Performance Tip:** For large grids with dynamic data, always use the Data Source property. GridView will only render visible items, keeping your app fast and responsive.
{% endhint %}

***

### Data Source Property

The **Data Source** is the most critical property of GridView. It determines what data the grid will display and how many items it will contain.

#### How to Configure the Data Source

1. In the properties panel, locate the **`Data Source`** field.
2. You can provide data in two ways:

**Option 1: Static JsonArray**

Enter a fixed JSON array directly:

```json
[
  {"name": "Product 1", "image": "url1.jpg", "price": 29.99},
  {"name": "Product 2", "image": "url2.jpg", "price": 39.99},
  {"name": "Product 3", "image": "url3.jpg", "price": 19.99}
]
```

This is useful for prototyping or displaying a small, unchanging grid.

**Option 2: Dynamic Expression**

Bind the data source to an expression that returns a `JsonArray`:

* **From an API Response:** `${apiResponse.data.products}`
* **From App State:** `${appState.galleryImages}`
* **From a Variable:** `${myGridData}`

The GridView will automatically update whenever the data source changes.

#### Accessing Item Data with `currentItem`

When using a data source, inside the child template you have access to:

* **`currentItem`**: The data for the current grid item being rendered.
  * For objects: `${currentItem.name}`, `${currentItem.price}`
  * For simple values: `${currentItem}`
* **`index`**: The zero-based index of the current item.

{% hint style="warning" %}
**Important:** When using a Data Source, it must be a `JsonArray`. If you bind it to a non-array value or an invalid expression, the GridView will not render any items.
{% endhint %}

***

### Properties

#### Grid Layout

<table><thead><tr><th width="200">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Cross Axis Count</code></td><td>(Required) The number of columns in the grid. This determines how many items appear per row. For example, <code>3</code> creates a 3-column grid.</td></tr><tr><td><code>Main Axis Spacing</code></td><td>The vertical space between rows in pixels. Controls the gap between items stacked vertically.</td></tr><tr><td><code>Cross Axis Spacing</code></td><td>The horizontal space between columns in pixels. Controls the gap between items placed side-by-side.</td></tr></tbody></table>

#### Scrolling Behavior

<table><thead><tr><th width="200">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Controller</code></td><td>An optional <code>Scroll Controller</code> variable to programmatically control the scroll position. Learn how to create and use scroll controllers in the <a href="broken-reference">Variables documentation</a>.</td></tr><tr><td><code>Allow Scroll</code></td><td>If <code>true</code>, the grid will be scrollable. If <code>false</code>, scrolling is disabled. Default is <code>true</code>.</td></tr><tr><td><code>Shrink Wrap</code></td><td>If <code>true</code>, the GridView will size itself to fit its children instead of expanding to fill available space. Useful when nesting inside another scrollable widget, but use with caution as it can impact performance.</td></tr></tbody></table>

### Controller Integration

The `Controller` property allows you to programmatically control the scroll position of the GridView. This is done by creating a **Scroll Controller** variable and binding it to the GridView.

#### How to Use a Scroll Controller

1. **Create a Scroll Controller Variable**
   * Navigate to **Variables** in your project.
   * Add a new variable of type **Scroll Controller**.
   * Give it a name, such as `gridScrollController`.
2. **Bind the Controller to the GridView**
   * Select the GridView widget.
   * In the `Controller` property, enter an expression referencing your variable: `${gridScrollController}`.
3. **Control the Scroll Position**
   * Use the **Control Object** action to invoke methods on the controller (such as `jumpTo`, `animateTo`, etc.).
   * For a complete list of available controller methods and their usage, see the [Variables documentation](https://docs.digia.tech/ui-building-blocks/widgets/scrolling-widgets/broken-reference).

{% hint style="info" %}
**Tip:** You can use the same controller for both programmatic scrolling (via Control Object actions) and scroll-driven animations (via Animation Builder).
{% endhint %}

***

### Guides

For detailed step-by-step tutorials on common GridView patterns, see:

{% content-ref url="broken-reference" %}
[Broken link](https://docs.digia.tech/ui-building-blocks/widgets/scrolling-widgets/broken-reference)
{% endcontent-ref %}

{% content-ref url="broken-reference" %}
[Broken link](https://docs.digia.tech/ui-building-blocks/widgets/scrolling-widgets/broken-reference)
{% endcontent-ref %}

***

### Default Properties

The GridView widget supports all [default-properties](https://docs.digia.tech/ui-building-blocks/widgets/default-properties "mention").

***

### Best Practices

* **Choose the right Cross Axis Count** for your content and screen size. Too many columns can make items too small; too few can waste space.
* **Control item sizing** through the child widget template dimensions.
* **Optimize item templates** to ensure smooth scrolling performance, especially for large grids.
* **Handle empty states** gracefully with clear messaging when no data is available.
* **Use spacing properties** to create visual breathing room between items.
* **Consider responsive design**: For different screen sizes, you might want to adjust `Cross Axis Count` dynamically.
* **Avoid nesting scrollable widgets** in the same direction to prevent scroll conflicts.
