> Markdown version of [Flow Usage](https://vaadin.com/docs/v23/components/grid/flow). Section index: [llms.txt](https://vaadin.com/docs/v23/components/llms.txt)

# Using Grid in Flow

Grid is a feature-rich component and therefore complex. Due to the server-driven nature of the component, there are some exclusive features available for the Java API and when using Grid together with Vaadin Flow. This page shows how to use Grid in a Flow application. It also explains the unique features, such as configuring Lit renderers instead of generic component renderers and styling the component with the Theme property.

## <a id="binding-to-data"></a>Binding to Data

`Grid` is bound to a `List` of items, by default. You can use the `setItems()` method to set the items.

For example, to show a list of beans in a `Grid`, you could do something like this:

```java
// Have some data
List<Person> people = Arrays.asList(
        new Person("Nicolaus Copernicus", 1543),
        new Person("Galileo Galilei", 1564),
        new Person("Johannes Kepler", 1571));

// Create a grid bound to the list
Grid<Person> grid = new Grid<>();
grid.setItems(people);
grid.addColumn(Person::getName).setHeader("Name");
grid.addColumn(Person::getYearOfBirth)
        .setHeader("Year of birth");

layout.add(grid);
```

Behind the scenes, `Grid` uses the `DataProvider` interface to communicate with the backend. The `setItems()` method is a shorthand to create a `ListDataProvider`. For a large amount of data or other advanced use cases, you should probably use the `DataProvider` interface and lazy loading. See [Data Providers](https://vaadin.com/docs/v23/binding-data/data-provider.md) for more.

To function, components such as the `Grid` and `ComboBox` require that the assigned items have identifiers that are *stable* and *unique*. This usually requires a proper implementation of the `hashCode()` and `equals()` methods as described in the [section](https://vaadin.com/docs/v23/binding-data/data-provider.md#data-binding.data-provider.item-identifiers).

## <a id="handling-selection-changes"></a>Handling Selection Changes

The `Grid` doesn’t implement directly the `HasValue` interface. Other selection components do typically implement this interface. Therefore, selection handling in the `Grid` is different from typical selection components. The `Grid` supports three selection options: single selection, multiple selection, and no selection. Each option is defined by a specific selection model.

For basic switching between selection models, you can use the `setSelectionMode(SelectionMode)` method. Possible options are `SINGLE` (default), `MULTI`, or `NONE`.

To access the selection API or to use Grid as an input field with `Binder`, you can use `asSingleSelect()` or `asMultiSelect()`, depending on the currently defined selection mode. Both the `SingleSelect` and `MultiSelect` interfaces implement the `HasValue` interface. In the `MultiSelect` interface, the value type is a `Set` of the item type.

For example, when using the `HasValue` interface with single and multi-select mode, you could do something like this:

```java
Grid<Person> grid = new Grid<>();

grid.setSelectionMode(SelectionMode.SINGLE);
SingleSelect<Grid<Person>, Person> personSelect =
        grid.asSingleSelect();
// personSelect can now be used with Binder or
// HasValue interface
personSelect.addValueChangeListener(e -> {
    Person selectedPerson = e.getValue();
});

grid.setSelectionMode(SelectionMode.MULTI);
MultiSelect<Grid<Person>, Person> multiSelect =
        grid.asMultiSelect();
multiSelect.addValueChangeListener(e -> {
    Set<Person> selectedPersons = e.getValue();
});
```

Alternatively, you can use a grid-specific selection API. To get the selected value or values in any selection model, you can use a `SelectionListener`, with the provided generic `SelectionEvent`, to get the selected value or values.

To use `addSelectionListener()` to get all selected items, for example, you could do this:

```java
Grid<Person> grid = new Grid<>();

// switch to multiselect mode
grid.setSelectionMode(SelectionMode.MULTI);

grid.addSelectionListener(event -> {
   Set<Person> selected = event.getAllSelectedItems();
   message.setText(selected.size() + " items selected");
});
```

> **Note:** The listener is attached to the selection model and not the grid. It stops getting events when the selection mode is changed.

You can use the `select(T)` method to select values, programmatically. In multi-selection mode, this adds the given item to the selection.

The example here is using the `select(T)` method:

```java
// in single-select, only one item is selected
grid.select(defaultItem);

// switch to multi select, clears selection
grid.setSelectionMode(SelectionMode.MULTI);
// Select items 2-4
people.subList(2, 3).forEach(grid::select);
```

You can get the current selection from the `Grid` using the `getSelectedItems()` method. The returned `Set` contains one item in single-selection mode, or several items in multi-selection mode.

> **Warning:** If you change the grid’s selection mode, it clears the selection and fires a selection event. To keep the previous selection, reset the selection afterwards using the `select()` method.

> **Warning:** If you change the grid’s items with either `setItems()` or the used `DataProvider`, it clears the selection and fires a selection event. To maintain the previous selection, reset the selection afterwards using the `select()` method.

### <a id="selection-models"></a>Selection Models

You can access the used selection model using the `getSelectionModel()` method. The return type is the `GridSelectionModel`, which has a generic selection model API. However, you can cast that to the specific selection model type, typically either `SingleSelectionModel` or `MultiSelectionModel`.

You can also get the selection model using the `setSelectionMode(SelectionMode)` method.

You could use the `setSelectionMode(SelectionMode)` method, for example, to get the selection model like so:

```java
// the default selection model
GridSingleSelectionModel<Person> defaultModel =
    (GridSingleSelectionModel<Person>) grid
        .getSelectionModel();

// Use multi-selection mode
GridMultiSelectionModel<Person> selectionModel =
    (GridMultiSelectionModel<Person>) grid
        .setSelectionMode(SelectionMode.MULTI);
```

#### <a id="single-selection-model"></a>Single-Selection Model

Obtaining a reference to the `SingleSelectionModel` allows you access to a fine-grained API for the single-selection use case.

You can use the `addSingleSelect(SingleSelectionListener)` method to access `SingleSelectionEvent`, which includes additional convenience methods and API options.

In single-selection mode, it’s possible to control whether the empty (null) selection is allowed. This is enabled by default.

Disallowing empty (null) selection, for example, using the `setDeselectAllowed()` method would look like this:

```java
// preselect value
grid.select(defaultItem);

GridSingleSelectionModel<Person> singleSelect =
    (GridSingleSelectionModel<Person>) grid
        .getSelectionModel();

// disallow empty selection
singleSelect.setDeselectAllowed(false);
```

#### <a id="multi-selection-model"></a>Multi-Selection Model

In multi-selection mode, a user can select multiple items by selecting checkboxes in the left column.

Obtaining a reference to the `MultiSelectionModel` allows you access to a fine-grained API for the multi-selection use case.

You can use the `addMultiSelectionListener(MultiSelectionListener)` method to access `MultiSelectionEvent`, which includes additional convenience methods and API options.

For example, you could use the `addMultiSelectionListener()` method to access selection changes like this:

```java
// Grid in multi-selection mode
Grid<Person> grid = new Grid<>();
grid.setItems(people);
GridMultiSelectionModel<Person> selectionModel =
    (GridMultiSelectionModel<Person>) grid
        .setSelectionMode(SelectionMode.MULTI);

selectionModel.selectAll();

selectionModel.addMultiSelectionListener(event -> {
    message.setText(String.format(
            "%s items added, %s removed.",
            event.getAddedSelection().size(),
            event.getRemovedSelection().size()));

    // Allow deleting only if there's any selected
    deleteSelected.setEnabled(
            event.getNewSelection().isEmpty());
});
```

## <a id="handling-item-click-events"></a>Handling Item-Click Events

It’s possible to handle item-click or double-click events, in addition to handling selection events. These can be used with selection events or on their own.

For example, to disable the selection mode using `SelectionMode.NONE`, but still get item-click events, you would do this:

```java
grid.setSelectionMode(SelectionMode.NONE);
grid.addItemClickListener(event -> System.out
        .println(("Clicked Item: " + event.getItem())));
```

The clicked item here, together with other information about the click, is available via the event. Selection events are no longer available, and no visual selection is displayed when a row is clicked.

It’s possible to get separate selection and click events. An example of this follows, using `Grid` in multi-selection mode with an added click or double-click listener:

```java
grid.setSelectionMode(SelectionMode.MULTI);
grid.addItemDoubleClickListener(event ->
        copy(grid.getSelectedItems()));
```

In the example code here, the local `copy()` method is called with the currently selected items when the user double-clicks a row.

## <a id="configuring-columns"></a>Configuring Columns

The `addColumn()` method allows you to add columns to the `Grid`. The column configuration is defined in `Grid.Column` objects that are returned by the `addColumn()` method. The `getColumns()` method returns a list of currently configured columns.

The setter methods in `Column` have fluent-API functionality, making it easy to chain configuration calls for columns.

Below is an example of chaining column configuration calls:

```java
Column<Person> nameColumn = grid
    .addColumn(Person::getName)
    .setHeader("Name")
    .setFlexGrow(0)
    .setWidth("100px")
    .setResizable(false);
```

### <a id="column-keys"></a>Column Keys

You can set an identifier key for a column using the `setKey()` method. This allows you to retrieve the column from the grid at any time.

Below is an example using the `setKey()` method to set an identifier key for a column:

```java
nameColumn.setKey("name");
grid.getColumnByKey("name").setWidth("100px");
```

### <a id="automatically-adding-columns"></a>Automatically Adding Columns

You can configure `Grid` to add columns automatically for every property in a bean by passing the class of the bean type to the grid’s constructor. The property names are set as the column keys, and you can use them to further configure the columns.

Below is an example in which columns are added automatically by passing the bean-type class to the constructor:

```java
Grid<Person> grid = new Grid<>(Person.class);
grid.getColumnByKey("yearOfBirth").setFrozen(true);
```

This constructor only adds columns for the direct properties of the bean type. The values are displayed as strings.

You can add columns for nested properties by using the dot notation with the `setColumn(String)` method.

Below is an example of adding a column for `postalCode`. It assumes `Person` has a reference to an `Address` object that has a `postalCode` property.

```java
grid.addColumn("address.postalCode");
```

The column’s key here is "address.postalCode" and its header is "Postal Code". To use these `String` properties in `addColumn()`, you need to use the `Grid` constructor, which takes a bean-class parameter.

#### <a id="defining-ordering-automatically-added-columns"></a>Defining & Ordering Automatically Added Columns

You can define which columns display, and the order in which they are displayed, in the grid, using the `setColumns()` method.

Below is an example in which columns are defined and they’re ordered using the `setColumns()` method:

```java
Grid<Person> grid = new Grid<>(Person.class);
grid.setColumns("name", "age", "address.postalCode");
```

> **Tip:** You can also use the `setColumns()` method to reorder the columns you already have.

> **Note:** When calling `setColumns()`, all columns that are currently present in the grid are removed, and only those passed as parameters are added.

To add custom columns before the auto-generated columns, use instead the `addColumns()` method. You can avoid creating the auto-generated columns by using the `Grid(Class, boolean)` constructor.

Below is an example of adding custom columns:

```java
Grid<Person> grid = new Grid<>(Person.class, false);
grid.addColumn(person -> person.getName().split(" ")[0])
    .setHeader("First name");
grid.addColumns("age", "address.postalCode");
```

> **Note:** An `IllegalArgumentException` is thrown if you try to add columns that are already present in the grid.

#### <a id="sortable-automatic-columns"></a>Sortable Automatic Columns

All property-based columns are sortable, by default, if the property type implements `Comparable`.

Many data types, such as `String`, `Number`, primitive types and `Date`/`LocalDate`/`LocalDateTime` are `Comparable`, and therefore also sortable by default.

To make the column of a non-comparable property type sortable, you need to define a custom `Comparator`. See [Column Sorting](#column-sorting) for more.

You can disable sorting for a specific column by using the `setSortable()` method.

Below is an example of this, disabling sorting on the `address.postalCode` column:

```java
grid.getColumnByKey("address.postalCode")
        .setSortable(false);
```

You can also define a list of columns as sortable by using the `setSortableColumns()` method. This makes all other columns not sortable.

The example here shows how to set defined columns as sortable:

```java
// All columns except "name" and "yearOfBirth"
// are not sortable
grid.setSortableColumns("name", "yearOfBirth");
```

### <a id="column-headers-footers"></a>Column Headers & Footers

By default, columns don’t have a header or a footer. They need to be set explicitly using the `setHeader()` and `setFooter()` methods. Both methods have two overloads: one accepts a plain text string, and the other a `LitRenderer`.

Below is an example of how to set headers and footers:

```java
// Sets a simple text header
nameColumn.setHeader("Name");
// Sets a header using Html component,
// in this case bolding the caption "Name"
nameColumn.setHeader(new Html("<b>Name</b>"));

// Similarly for the footer
nameColumn.setFooter("Name");
nameColumn.setFooter(new Html("<b>Name</b>"));
```

See [Using Lit Renderers](#using-lit-renderers) for more information.

### <a id="column-reordering"></a>Column Reordering

Column reordering isn’t enabled by default. You can use the `setColumnReorderingAllowed()` method to allow column reordering by dragging.

Below is an example of how to enable column reordering:

```java
grid.setColumnReorderingAllowed(true);
```

### <a id="hiding-columns"></a>Hiding Columns

Columns can be hidden by calling the `setVisible()` method in `Column`.

> **Note:** A hidden column still sends the data required to render it to the client side. The best practice is to remove — or not add — columns if the data isn’t needed on the client side. This reduces the amount of data sent, and it thereby lessens the load on the client.

### <a id="removing-columns"></a>Removing Columns

You can remove a single column using the `removeColumn(Column)` and `removeColumnByKey(String)` methods. You can also remove all currently configured columns using the `removeAllColumns()` method.

### <a id="setting-column-widths"></a>Setting Column Widths

By default, columns don’t have a defined width. They resize automatically based on the data displayed.

You can set the column width either relatively, using flex grow ratios by using the `setFlexGrow()` method, or you can set them explicitly using a CSS string value with `setWidth()` — with flex grow set to `0`.

You can also enable user column resizing using the `setResizable()` method. The column is resized by dragging the column divider.

### <a id="setting-frozen-columns"></a>Setting Frozen Columns

You can freeze columns using the `setFrozen()` method. This ensures the set number of columns on the left remain static and visible when the user scrolls horizontally.

When columns are frozen, user reordering is limited to the frozen columns.

Below is an example of setting a column as frozen:

```java
nameColumn.setFrozen(true);
```

### <a id="grouping-columns"></a>Grouping Columns

You can group multiple columns together by adding them in the `HeaderRow` of the grid.

When you retrieve the `HeaderRow`, using the `prependHeaderRow()` or `appendHeaderRow()` methods, you can then group the columns using the `join()` method. Additionally, you can use the `setText()` and `setComponent()` methods on the join result to set the text or component for the joined columns.

For example, you can group columns like so:

```java
// Create a header row
HeaderRow topRow = grid.prependHeaderRow();

// group two columns under the same label
topRow.join(nameColumn, ageColumn)
        .setComponent(new Label("Basic Information"));

// group the other two columns in the same header row
topRow.join(streetColumn, postalCodeColumn)
        .setComponent(new Label("Address Information"));
```

## <a id="using-renderers-in-columns"></a>Using Renderers in Columns

You can configure columns to use a renderer to show the data in the cells. Conceptually, there are three types of renderer:

1. **Basic Renderer**: Renders basic values, such as dates and numbers.

2. **Lit Renderer**: Renders content using HTML markup and Lit data-binding syntax.

3. **Component Renderer**: Renders content using arbitrary components.

### <a id="using-basic-renderers"></a>Using Basic Renderers

You can use several basic renderers to configure grid columns.

#### <a id="local-date-renderer"></a>Local Date Renderer

Use `LocalDateRenderer` to render `LocalDate` objects in the cells.

An example of this is below, which is using `LocalDateRenderer` with the `addColumn()` method:

```java
grid.addColumn(new LocalDateRenderer<>(
        Item::getEstimatedDeliveryDate,
        () -> DateTimeFormatter.ofLocalizedDate(
                FormatStyle.MEDIUM)))
    .setHeader("Estimated delivery date");
```

`LocalDateRenderer` works with a `DateTimeFormatter` or a `String` format to render `LocalDate` objects.

Here is an example using a `String` format to render the `LocalDate` object:

```java
grid.addColumn(new LocalDateRenderer<>(
        Item::getEstimatedDeliveryDate,
        "dd/MM/yyyy"))
    .setHeader("Estimated delivery date");
```

#### <a id="local-date-time-renderer"></a>Local Date Time Renderer

Use `LocalDateTimeRenderer` to render `LocalDateTime` objects in the cells.

Below is an example using `LocalDateTimeRenderer` with the `addColumn()` method:

```java
grid.addColumn(new LocalDateTimeRenderer<>(
        Item::getPurchaseDate,
        () -> DateTimeFormatter.ofLocalizedDateTime(
                FormatStyle.SHORT,
                FormatStyle.MEDIUM)))
    .setHeader("Purchase date and time");
```

`LocalDateTimeRenderer` also works with `DateTimeFormatter` — with separate styles for date and time — or a `String` format to render `LocalDateTime` objects.

Here is an example using a `String` format to render the `LocalDateTime` object:

```java
grid.addColumn(new LocalDateTimeRenderer<>(
        Item::getPurchaseDate,
        "dd/MM HH:mm:ss")
).setHeader("Purchase date and time");
```

#### <a id="number-renderer"></a>Number Renderer

Use `NumberRenderer` to render any type of `Number` in the cells. It’s especially useful for rendering floating-point values.

The example here is using `NumberRenderer` with the `addColumn()` method:

```java
grid.addColumn(new NumberRenderer<>(Item::getPrice,
        NumberFormat.getCurrencyInstance())
).setHeader("Price");
```

It’s possible to set up the `NumberRenderer` with a `String` format, and an optional null representation.

For example, to use a `String` format to render a price do something like this:

```java
grid.addColumn(new NumberRenderer<>(
        Item::getPrice, "$ %(,.2f",
        Locale.US, "$ 0.00")
).setHeader("Price");
```

#### <a id="native-button-renderer"></a>Native Button Renderer

Use `NativeButtonRenderer` to create a clickable button in the cells. This creates a native `<button>` on the client side. Click events — or tap for touch devices — are handled on the server side.

Below is an example using `NativeButtonRenderer` with the `addColumn()` method:

```java
grid.addColumn(
    new NativeButtonRenderer<>("Remove item",
       clickedItem -> {
           // remove the item
    })
);
```

You can configure a custom label for each item.

The example here is configuring `NativeButtonRenderer` to use a custom label:

```java
grid.addColumn(new NativeButtonRenderer<>(
        item -> "Remove " + item,
        clickedItem -> {
            // remove the item
        })
);
```

### <a id="using-lit-renderers"></a>Using Lit Renderers

Providing a `LitRenderer` for a column allows you to define the content of cells using HTML markup, and to use Lit notations for data binding and event handling.

The example here is using `LitRenderer` to embolden the names of the persons:

```java
Grid<Person> grid = new Grid<>();
grid.setItems(people);

grid.addColumn(LitRenderer
       .<Person>of("<b>${item.name}</b>")
       .withProperty("name", Person::getName)
).setHeader("Name");
```

The template string here is passed for the static `LitRenderer.of()` method. Every property in the template needs to be defined in the `withProperty()` method. The `${item.name}` is the Lit syntax for interpolating properties into the template. See the [Lit documentation](https://lit.dev/docs/templates/overview/) for more.

When using a custom Web Component or a Vaadin element in a Lit renderer, remember to import the component. This can be done using [`@JsModule`](https://vaadin.com/api/platform/com/vaadin/flow/component/dependency/JsModule.html) or [`@Uses`](https://vaadin.com/api/platform/com/vaadin/flow/component/dependency/Uses.html), if the component has a server-side counterpart. It ensures that all `StyleSheet`, `HtmlImport`, and `JavaScript` dependencies for the component are loaded when the Grid is used.

#### <a id="creating-custom-properties"></a>Creating Custom Properties

You can use a `LitRenderer` to create and display new properties, properties the item didn’t originally contain.

The example below is using `LitRenderer` to compute the approximate age of each person and add it in a new column. Age is the current year minus the birth year.

```java
grid.addColumn(LitRenderer
        .<Person>of("${item.age} years old")
        .withProperty("age",
                person -> Year.now().getValue()
                        - person.getYearOfBirth())
).setHeader("Age");
```

#### <a id="using-expressions"></a>Using Expressions

Lit templates can include any type of JavaScript expression, not limited to binding single property values.

For example, by evaluating the person’s age in the template expression, the age column could also be written as this:

```java
grid.addColumn(LitRenderer
        .<Person>of("${new Date().getFullYear() - item.yearOfBirth} years old")
        .withProperty("yearOfBirth", Person::getYearOfBirth);
).setHeader("Age");
```

#### <a id="binding-beans"></a>Binding Beans

If an object contains a bean property that has sub-properties, it’s only necessary to make the bean accessible by calling the `withProperty()` method. The sub-properties become accessible automatically.

> **Warning:** All properties of the bean, even ones which aren’t used in the template, are sent to the client. Therefore, use this feature with caution.

The example that follows is using the `withProperty()` method to access multiple sub-properties. This assumes that `Person` has a field for the `Address` bean, which has `street`, `number` and `postalCode` fields with corresponding getter and setter methods.

```java
grid.addColumn(LitRenderer.<Person>of(
        "<div>${item.address.street}, number " +
        "${item.address.number}<br>" +
        "<small>${item.address.postalCode}</small>" +
        "</div>")
        .withProperty("address", Person::getAddress))
    .setHeader("Address");
```

#### <a id="handling-events"></a>Handling Events

You can define event handlers for the elements in your template, and hook them to server-side code, by calling the `withFunction()` method on your `LitRenderer`. This is useful for editing items in the grid.

The example that follows is using the `withFunction()` method to map defined method names to server-side code. The snippet adds a new column with two buttons: one to edit a property of the item; and one to remove the item. Both buttons define a method to call for `click` events.

```java
grid.addColumn(LitRenderer.<Person>of(
     "<button @click=\"${handleUpdate}\">Update</button>" +
     "<button @click=\"${handleRemove}\">Remove</button>")
    .withFunction("handleUpdate", person -> {
        person.setName(person.getName() + " Updated");
        grid.getDataProvider().refreshItem(person);
    }).withFunction("handleRemove", person -> {
        ListDataProvider<Person> dataProvider =
            (ListDataProvider<Person>) grid
                .getDataProvider();
        dataProvider.getItems().remove(person);
        dataProvider.refreshAll();
    })).setHeader("Actions");
```

When the server-side data used by the grid here is edited, the grid’s `DataProvider` is refreshed by calling the `refreshItem()` method. This ensures that the changes are in the element. When an item is removed, the `refreshAll()` method call ensures that all of the data is updated.

You will need to use Lit notation for event handlers. The `@click` is Lit syntax for the native `click`. The `LitRenderer` has a fluent API, so you can chain the commands, like `LitRenderer.of().withProperty().withProperty().withFunction()…​`

The `withFunction()` handler can also receive more data in addition to the item. To pass additional data from client to the server-side handler, you need to invoke the function in the Lit template with the desired extra parameters. The additional data can be accessed via the second handler parameter — of type `JsonArray`.

Below is an example of this:

```java
grid.addColumn(LitRenderer.<Person>of(
     "<input .value=\"${item.profession}\" @change=\"${e => changed(e.target.value)}\">")
    .withFunction("changed", (person, args) -> {
        String profession = args.getString(0);
        person.setProfession(profession);
        grid.getDataProvider().refreshItem(person);
    }).withProperty("profession", Person::getProfession));
```

The functions defined by the `withFunction()` method can be called with any number of additional parameters. The additional argument of type `String` (the updated profession) is obtained from the second handler parameter with `args.getString(0)`, where the number is the index of the argument in the `JsonArray`.

### <a id="using-component-renderers"></a>Using Component Renderers

You can use any component in the grid cells by providing a `ComponentRenderer` for a column. To define how the component is generated for each item, you need to pass a `Function` for the `ComponentRenderer`.

For example, to add a column that contains a different icon depending on the person’s gender, you would do something like this:

```java
Grid<Person> grid = new Grid<>();
grid.setItems(people);

grid.addColumn(new ComponentRenderer<>(person -> {
    if (person.getGender() == Gender.MALE) {
        return VaadinIcon.MALE.create();
    } else {
        return VaadinIcon.FEMALE.create();
    }
})).setHeader("Gender");
```

It’s also possible to provide a separate `Supplier` to create the component, and a `Consumer` to configure it for each item.

The example below uses `ComponentRenderer` with a `Consumer`:

```java
SerializableBiConsumer<Div, Person> consumer =
        (div, person) -> div.setText(person.getName());
grid.addColumn(
        new ComponentRenderer<>(Div::new, consumer))
    .setHeader("Name");
```

If the component is the same for each item, you only need to provide the `Supplier`.

The example here is using `ComponentRenderer` with a `Supplier`:

```java
grid.addColumn(
    new ComponentRenderer<>(
             () -> VaadinIcon.ARROW_LEFT.create()));
```

You can create complex content for the grid cells by using the component APIs.

This example is using `ComponentRenderer` to create complex content that listens for events and wraps multiple components in layouts:

```java
grid.addColumn(new ComponentRenderer<>(person -> {

    // text field for entering a new name for the person
    TextField name = new TextField("Name");
    name.setValue(person.getName());

    // button for saving the name to backend
    Button update = new Button("Update", event -> {
        person.setName(name.getValue());
        grid.getDataProvider().refreshItem(person);
    });

    // button that removes the item
    Button remove = new Button("Remove", event -> {
        ListDataProvider<Person> dataProvider =
            (ListDataProvider<Person>) grid
                .getDataProvider();
        dataProvider.getItems().remove(person);
        dataProvider.refreshAll();
    });

    // layouts for placing the text field on top
    // of the buttons
    HorizontalLayout buttons =
            new HorizontalLayout(update, remove);
    return new VerticalLayout(name, buttons);
})).setHeader("Actions");
```

> **Note:** `addComponentColumn()` is a shorthand for `addColumn()` with a `ComponentRenderer`.

Editing grid items requires refreshing the grid’s `DataProvider`. The reasoning is the same as for [Handling Events](#handling-events) mentioned earlier. See [Data Providers](https://vaadin.com/docs/v23/binding-data/data-provider.md) for more.

## <a id="enabling-expanding-rows"></a>Enabling Expanding Rows

The `Grid` supports expanding rows that reveal more details about the items. The additional information is hidden, unless the user chooses to reveal it, keeping the grid appearance clean and simple, while simultaneously allowing detailed explanations.

You can enable expanding rows using the `setItemDetailsRenderer()` method, which allows either a `LitRenderer` or a `ComponentRenderer` to define how the details are rendered.

Below is an example using the `setItemDetailsRenderer()` method with a `ComponentRenderer`:

```java
grid.setItemDetailsRenderer(
    new ComponentRenderer<>(person -> {
        VerticalLayout layout = new VerticalLayout();
        layout.add(new Label("Address: " +
                person.getAddress().getStreet() + " " +
                person.getAddress().getNumber()));
        layout.add(new Label("Year of birth: " +
                person.getYearOfBirth()));
        return layout;
}));
```

By default, the row’s detail opens by clicking the row. Clicking the row again, or clicking another row to open its detail, automatically closes the first row’s detail. You can disable this behavior by calling the `grid.setDetailsVisibleOnClick(false)` method. You can show and hide item details programmatically using the `setDetailsVisible()` method, and test whether an item’s detail is visible using the `isDetailsVisible()` method.

> **Note:** By default, items are selected by clicking them. If you want the click action only to show the item details without selection, you need to use the `grid.setSelectionMode(SelectionMode.NONE)` method.

## <a id="column-sorting"></a>Column Sorting

Column sorting in the grid has an order to its process. The first click on the column header sorts the column. The second click reverses the sort order. And the third click resets the column to its unsorted state.

If multi-sorting is enabled, the user can sort by multiple columns. Then the first click sorts the first column, while subsequent clicks on a second and more sortable column headers, add secondary and more sort criteria.

### <a id="enabling-column-sorting"></a>Enabling Column Sorting

For columns that have been created from a property name (`grid.addColumn("firstName")`), sorting is enabled by default — if the type of the property implements `Comparable`. In general this only applies to grids that have been created from a class name (`new Grid(Person.class)`).

For columns that have been created from a `ValueProvider` (`grid.addColumn(Person::getFirstName)`), or from a renderer such as `LitRenderer` (`grid.addColumn(new LitRenderer<Person>(…​))`), sorting is not enabled by default.

Sorting for a column can be enabled or disabled manually:

```java
// Enabled sorting for a column
column.setSortable(true);

// Disable sorting for a column
column.setSortable(false);

// Check whether a column is sortable
var isSortable = column.isSortable();
```

Depending on how the column was created, it may need additional configuration. In order to determine this, you need to consider the two sorting mechanisms supported by Grid: in-memory sorting or backend sorting.

In-memory sorting is sorting that is automatically applied by the framework when using an in-memory data provider. Items are sorted using a `Comparator` that can either be created automatically by the column or has to be specified manually by the developer.

Backend sorting is applied by providing a list of `QuerySortOrder` objects a custom `DataProvider` implemented by the developer. Sort order objects contain the property names that the developer must use for sorting items in their backend, such as a database. See [Data Providers](https://vaadin.com/docs/v23/binding-data/data-provider.md#Sorting) for more.

With that in mind, you can determine which columns are automatically configured for in-memory or backend sorting:

- For columns created from a property name, in-memory sorting is automatically configured if the type of the property implements `Comparable`. Otherwise, a custom comparator must be provided by the developer. Backend sorting is configured automatically in any case, as the column knows the property name to pass to the data provider.

- For columns created from a `ValueProvider`, only in-memory sorting is configured automatically, where the value provider is used to build a comparator. Backend sorting is not configured automatically, as the column does not know which property name to pass to the data provider.

- For columns created from a renderer, neither in-memory sorting, nor backend sorting is configured automatically. The column cannot create a comparator from the renderer, nor does it know the property name to pass to the data provider.

If either sort mechanism is not configured automatically, it can be configured manually as explained in the following sections.

#### <a id="configuring-in-memory-sorting"></a>Configuring In-Memory Sorting

For in-memory sorting, a custom comparator can be configured using `Column.setComparator`. Use this if a column is not automatically configured for in-memory sorting, or if you want to customize the in-memory sorting behavior.

The example below shows how to configure a comparator for a column using a `LitRenderer`. The renderer shows the person’s name and email address, for sorting only the email address is used.

```java
grid.addColumn(LitRenderer.<Person>of(
        "<div>${item.name}<br>" +
        "<small>${item.email}</small></div>")
        .withProperty("name", Person::getName)
        .withProperty("email", Person::getEmail))
    .setComparator(Person::getEmail)
    .setHeader("Person");
```

This next example is customizing the in-memory sorting for a column created from a value provider by implementing a comparator that is not case-sensitive:

```java
grid.addColumn(Person::getName)
    .setComparator((person1, person2) ->
        person1.getName()
            .compareToIgnoreCase(person2.getName()))
    .setHeader("Name");
```

#### <a id="configuring-backend-sorting"></a>Configuring Backend Sorting

For backend sorting, the sort properties that are passed to a data provider can be configured using `Column.setSortProperty`. The method allows for providing multiple sort properties, which are passed to the data provider in the specified order. Use this if a column is not automatically configured for backend sorting, or if you want to customize the backend sorting behavior.

The example here is configuring sort properties for a column created from a value provider:

```java
grid.addColumn(Person::getName)
        .setSortProperty("name", "email")
        .setHeader("Person");
```

The next example is setting a sort property for a column using a `LitRenderer`. The renderer shows the person’s name and email address, for sorting only the email address is used.

```java
grid.addColumn(LitRenderer.<Person>of(
        "<div>${item.name}<br>" +
        "<small>${item.email}</small></div>")
        .withProperty("name", Person::getName)
        .withProperty("email", Person::getEmail))
    .setSortProperty("email")
    .setHeader("Person");
```

An alternative way to configure backend sorting is to use a `SortOrderProvider`, which is called on demand when the sort order is changed. Use this if you need fine-grained control over how `QuerySortOrder` objects are created and sent to the `DataProvider`.

This example is defining a `SortOrderProvider` for backend sorting:

```java
grid.addColumn(Person::getName)
    .setSortOrderProvider(direction -> Arrays
        .asList(new QuerySortOrder("name", direction),
                new QuerySortOrder("email", direction))
        .stream())
    .setHeader("Person");
```

### <a id="enabling-multi-sorting"></a>Enabling Multi-Sorting

To allow users to sort by more than one column at the same time, you can use the `setMultiSort()` method to enable multi-sorting at the grid level.

This example is using the `setMultiSort()` method to enable multi-sorting:

```java
grid.setMultiSort(true);
```

### <a id="receiving-sort-events"></a>Receiving Sort Events

You can add a `SortListener` to the grid to receive general sort events. Each time sorting of the grid is changed, an event is fired. You can access the `DataCommunicator` to receive the sorting details.

The example below is using the `addSortListener()` method to add a `SortListener`:

```java
grid.addSortListener(event -> {
    String currentSortOrder = grid.getDataCommunicator()
            .getBackEndSorting().stream()
            .map(querySortOrder -> String.format(
                   "{sort property: %s, direction: %s}",
                   querySortOrder.getSorted(),
                   querySortOrder.getDirection()))
            .collect(Collectors.joining(", "));
    System.out.println(String.format(
            "Current sort order: %s. User-clicked: %s.",
            currentSortOrder, event.isFromClient()));
});
```

## <a id="styling-the-grid"></a>Styling the Grid

Styling the `Grid` component or any Vaadin component requires some Web Component and shadow-DOM knowledge. Styling depends on the component’s position in the DOM: If the component is in the shadow DOM, you can apply styling within the component or using variables. If the component is in the "normal" DOM (i.e., not in the shadow DOM), normal CSS styling applies.

Additionally, the `Grid` supports the `theme` attribute, which allows you to customize component styling.

`Celebrity` grid is used in styling examples below:

```java
Grid<Celebrity> grid = new Grid<>();
grid.setItems(Celebrity.getPeople());
grid.addClassName("styled");
grid.addColumn(new ComponentRenderer<>(person -> {
    TextField textField = new TextField();
    textField.setValue(person.getName());
    textField.addClassName("style-" +
            person.getGender());
    textField.addValueChangeListener(
        event -> person.setName(event.getValue()));
    return textField;
})).setHeader("Name");

grid.addColumn(new ComponentRenderer<>(person -> {
    DatePicker datePicker = new DatePicker();
    datePicker.setValue(person.getDob());
    datePicker.addValueChangeListener(event -> {
        person.setDob(event.getValue());
    });
    datePicker.addClassName("style-" +
            person.getGender());
    return datePicker;
})).setHeader("DOB");

grid.addColumn(new ComponentRenderer<>(person -> {
    Image image = new Image(person.getImgUrl(),
            person.getName());
    return image;
})).setHeader("Image");
```

### <a id="styling-with-the-theme-property"></a>Styling with the Theme Property

The default Lumo theme includes different variations that you can use to style the grid. You can provide one or more variations.

This example uses the `addThemeVariants()` method to define theme variations for the grid:

```java
grid.addThemeVariants(GridVariant.LUMO_NO_ROW_BORDERS,
        GridVariant.LUMO_NO_BORDER, GridVariant.LUMO_ROW_STRIPES);
```

### <a id="styling-with-css"></a>Styling with CSS

You can use normal CSS styling for the content in grid cells. Although the `Grid` component itself is in the shadow DOM, the actual values (i.e., cell contents) are in slots and therefore in the light DOM.

For example, you can set the maximum size for images in the grid cells like so:

```css
vaadin-grid vaadin-grid-cell-content img {
    max-height: 4em;
}
```

The `vaadin-grid-cell-content` is in the light DOM, and the selector `vaadin-grid vaadin-grid-cell-content` points to all of the grid’s cells.

You can also use a class to apply styles to a specific component instance. For example, to apply rounded borders and center images in a grid with a "styled" class name, you would do something like this:

```css
vaadin-grid.styled vaadin-grid-cell-content img {
    border-radius: 2em;
    margin-left: 50%;
    transform: translate(-50%);
}
```

To learn how to customize styles inside a component’s shadow DOM, see [Styling Components](https://vaadin.com/docs/v23/styling/custom-theme/styling-components.md).

`F478ED56-7248-4788-BC75-4E05605EB33F`
