dataGrid

dataGrid is designed to display and sort tabular data and provides means to manipulate rows and columns with great performance due to the lazy loading of data while scrolling.

  • XML element: dataGrid

  • Java class: DataGrid

Basics

An example of dataGrid declaration in the XML view descriptor is shown below:

<data readOnly="true">
    <collection id="usersDc"
                class="com.company.onboarding.entity.User"> (1)
        <fetchPlan extends="_base"/>
        <loader id="usersDl">
            <query>
                <![CDATA[select e from User e order by e.username]]>
            </query>
        </loader>
    </collection>
</data>
<layout>
    <dataGrid id="usersTable"
              width="100%"
              minHeight="20em"
              dataContainer="usersDc"> (2)
        <columns> (3)
            <column property="username"/>
            <column property="firstName"/>
            <column property="lastName"/>
            <column property="active"/>
            <column property="onboardingStatus"/>
            <column property="joiningDate"/>
        </columns>
    </dataGrid>
</layout>
1 Collection container for the User entity.
2 dataGrid is bound to the usersDc container using the dataContainer attribute.
3 The columns element defines which entity attributes are shown in the data grid columns.
data grid basics

Data Binding

Declarative Binding

Usually, you bind dataGrid to data declaratively in the view XML descriptor using the dataContainer attribute. It should refer to a collection container.

Using Key-Value Containers

You can bind the data grid to a key-value container to display the results of a query that returns scalar values and/or aggregates. For example:

<data readOnly="true">
    <keyValueCollection id="statusesDc">
        <loader id="statusesLoader">
            <query>
                <![CDATA[select o.department, o.onboardingStatus,
                count(o.onboardingStatus) from
                User o group by o.department, o.onboardingStatus]]>
            </query>
        </loader>
        <properties>
            <property name="department" datatype="string"/>
            <property name="onboardingStatus" datatype="int"/>
            <property name="count" datatype="int"/>
        </properties>
    </keyValueCollection>
</data>
<layout>
    <dataGrid width="100%" dataContainer="statusesDc">
        <columns>
            <column property="department"/>
            <column property="onboardingStatus"/>
            <column property="count"/>
        </columns>
    </dataGrid>
</layout>

Programmatic Binding

If you need to define a data container programmatically in the view controller, set the metaClass attribute instead of dataContainer in XML descriptor:

<dataGrid width="100%" id="dataGrid" metaClass="User">
    <columns>
        <column property="firstName"/>
        <column property="lastName"/>
        <column property="username"/>
        <column property="joiningDate"/>
        <column property="onboardingStatus"/>
    </columns>
</dataGrid>

In the view controller, use the ContainerDataGridItems class to bind the data grid to a data container:

@ViewComponent
private DataGrid<User> dataGrid;

@ViewComponent
private CollectionContainer<User> usersDc;

@Subscribe
public void onInit(InitEvent event) {
    dataGrid.setItems(new ContainerDataGridItems<>(usersDc));
}

Columns

The set of columns for a data grid is defined in the columns nested element. columns can have the following attributes:

  • includeAll includes all the attributes from the fetch plan that is defined in the data container.

    In the example below, we will show all the attributes from the fetch plan used in usersDc:

    <dataGrid width="100%"
              dataContainer="usersDc">
        <columns includeAll="true"/>
    </dataGrid>

    If the entity fetch plan contains a reference attribute, this attribute will be displayed according to its instance name. If you want to show a specific nested attribute, define it in the fetch plan as well as in the column element:

    <data readOnly="true">
        <collection class="com.company.onboarding.entity.UserStep" id="userStepsDc">
            <fetchPlan extends="_base">
                <property name="user" fetchPlan="_base">
                    <property name="department" fetchPlan="_base"/>
                </property>
            </fetchPlan>
            <loader id="userStepsDl">
                <query>
                    <![CDATA[select e from UserStep e]]>
                </query>
            </loader>
        </collection>
    </data>
    <layout>
        <dataGrid width="100%"
                  dataContainer="userStepsDc">
            <columns includeAll="true">
                <column property="user.department.name"/>
            </columns>
        </dataGrid>
    </layout>
  • exclude contains a comma-separated list of attributes that should not be displayed in the data grid.

    In the example below, we will show all the attributes excluding id, version, sortValue:

    <dataGrid width="100%"
              dataContainer="userStepsDc">
        <columns includeAll="true"
                 exclude="id,version,sortValue"/>
    </dataGrid>

Column

Each column is described in a nested column element.

To add column in Jmix Studio, select the columns element in the view descriptor XML or in the Jmix UI hierarchy panel and click on the Add→Column button in the Jmix UI inspector panel.

autoWidth

Enables or disables automatic width for this column.

When autoWidth = true, the column width is based on the column contents.

By default, this attribute is set to false.

editable

Specifies that an editor component will be created for this column.

See also Inline Editing.

flexGrow

Sets the flex grow ratio for this column. When set to 0, the column width is fixed.

Sets a footer text to the column.

The attribute value can either be the text itself or a key in the message bundle. In case of a key, the value should begin with the msg:// prefix.

frozen

Sets whether to freeze or unfreeze this column.

Columns are frozen in-place, freeze columns from left to right for a consistent outcome.

Sets a header text to the column.

The attribute value can either be the text itself or a key in the message bundle. In case of a key, the value should begin with the msg:// prefix.

key

Sets the user-defined identifier to map this column. The key can be used to fetch the column later with the getColumnByKey(String) method.

The key has to be unique within the data grid, and it can’t be changed after set once.

property

property specifies the name of an entity attribute displayed in the column. It can be either an attribute of the entity from the data container or a linked entity (use dot notation to traverse the object graph). For example:

<columns>
    <column property="user.firstName" sortable="false"/>
    <column property="user.lastName" sortable="false"/>
    <column property="step" frozen="true" sortable="true"/>
    <column property="dueDate" editable="true" sortable="true"/>
    <column property="user.department.name" sortable="false"/>
</columns>

resizable

When set to true, the column is user-resizable. By default, this attribute is set to false.

The column size changes can be tracked with ColumnResizeEvent.

sortable

Sets whether the user can sort this column or not.

The dataGrid sorting events can be tracked by SortEvent.

textAlign

Sets the column text align.

Three different column alignments are supported: START (default), CENTER, and END.

visible

Sets the column visibility value.

width

Sets the width of this column as a CSS-string.

Actions

The dataGrid component implements the HasActions interface and can contain custom actions, as well as standard list actions.

Data grid actions are defined in the nested actions element.

To add action in Jmix Studio, select the component in the view descriptor XML or in the Jmix UI hierarchy panel and click on the Add→Action button in the Jmix UI inspector panel.

If an action has a text, it is displayed as an item of the data grid context menu. Additionally, a data grid action can be assigned to a button located anywhere on the view.

You can create an hbox container to show action buttons above the data grid.

<hbox id="buttonsPanel" classNames="buttons-panel"> (1)
    <button id="createBtn" action="usersDataGrid.create"/>
    <button id="editBtn" action="usersDataGrid.edit"/>
    <button id="removeBtn" action="usersDataGrid.remove"/>
    <button id="infoBtn" action="usersDataGrid.getInfo"/>
</hbox>
<dataGrid width="100%" dataContainer="usersDc" id="usersDataGrid">
    <columns>
        <column property="username"/>
        <column property="firstName"/>
        <column property="lastName"/>
        <column property="active"/>
        <column property="onboardingStatus"/>
        <column property="joiningDate"/>
    </columns>
    <actions>
        <action id="create" type="list_create"/> (2)
        <action id="edit" type="list_edit"/>
        <action id="remove" type="list_remove"/>
        <action id="getInfo" text="Get Info"/> (3)
    </actions>
</dataGrid>
1 Define a buttonsPanel hbox container above the data grid.
2 Define the list_create standard action.
3 Define the getInfo custom action.
data grid actions

Using Renderers

The addColumn() and addComponentColumn() methods allow you to add columns to the data grid.

You can configure the added columns to use a renderer to show the data.

As an example, let’s create a generated column containing the user’s joining date using LocalDateRenderer.

@ViewComponent
private DataGrid<User> usersDtGr;

@Subscribe
public void onInit(InitEvent event) {
    usersDtGr.addColumn(new LocalDateRenderer<>
                    (User::getJoiningDate,"dd/MM"))
            .setHeader("Joining date");
}

In the following example, we will add a column displaying the user’s picture:

@ViewComponent
private DataGrid<User> usersDtGr;

@Autowired
private FileStorage fileStorage;

@Subscribe
public void onInit(InitEvent event) {
    Grid.Column<User> pictureColumn = usersDtGr.addComponentColumn(user -> { (1)
        FileRef fileRef = user.getPicture();
        if (fileRef != null) {
            Image image = uiComponents.create(Image.class); (2)
            image.setWidth("30px");
            image.setHeight("30px");
            image.setClassName("user-picture");

            StreamResource streamResource = new StreamResource(
                    fileRef.getFileName(),
                    () -> fileStorage.openStream(fileRef));
            image.setSrc(streamResource); (3)

            return image; (4)
        } else {
            return new Span();
        }
    })
            .setHeader("Picture")
            .setAutoWidth(true)
            .setFlexGrow(0);
    usersDtGr.setColumnPosition(pictureColumn,0);
}
1 Adds a new column that shows the image component.
2 The Image component instance is created using the UiComponents factory.
3 image gets its content from the given StreamResource by the reference stored in the picture attribute of the User entity.
4 The addComponentColumn() method returns the visual component to be shown in the column cells.

Inline Editing

dataGrid provides inline editing that allows users to manipulate grid data.

The columns with the editable = true attribute show components to edit the attributes of the corresponding entity. The component type for each editable column is selected automatically based on the type of the corresponding entity attribute.

The editorBuffered attribute defines whether the inline editor must be opened in buffered mode or not.

  • To make some column editable, set the value of the editable attribute to true.

  • Then you should start editing of a row either programmatically as described in the Vaadin documentation, or by defining the editorActionsColumn element, for example:

    <dataGrid width="100%" dataContainer="usersDc" id="editableUsersTable">
        <columns>
            <column property="username"/>
            <column property="firstName" editable="true"/>
            <column property="lastName" editable="true"/>
            <column property="active" editable="true"/>
            <column property="onboardingStatus"/>
            <editorActionsColumn width="8em" flexGrow="0">
                <editButton text="Edit" icon="PENCIL"/>
                <closeButton text="Close" icon="CLOSE"/>
            </editorActionsColumn>
        </columns>
    </dataGrid>
    data grid editing

editorActionsColumn

The editorActionsColumn element is used to create a custom column with edit buttons.

<editorActionsColumn width="16em" flexGrow="0">
    <editButton text="Edit" icon="PENCIL"/>
    <saveButton icon="CHECK" themeNames="success"/>
    <cancelButton icon="CLOSE" themeNames="error"/>
    <closeButton text="Close" icon="CLOSE"/>
</editorActionsColumn>

The following buttons can be included to the editor column:

  • editButton - starts editing of an item. Suitable for both buffered and non buffered mode.

  • saveButton - saves changes made in editor components. Suitable for buffered mode only.

  • cancelButton - discards changes made in editor components. Suitable for buffered mode.

  • closeButton - closes the edit mode. Suitable for non buffered mode only.

Each button supports a limited set of attributes of standard button: text, icon, title, classNames, themeNames, iconAfterText.

The editor column is added relatively to other columns. In case of includeAll="true", the editor column is added at the end.

DataGridEditor

The io.jmix.flowui.component.grid.editor.DataGridEditor interface provides additional editor functionality: configure an editor, open the editor, save and cancel a row editing, and utility methods for defining column edit components.

To support framework mechanisms like data containers, value sources, etc., the column editor component must be added using DataGridEditor methods (DataGridEditor#setColumnEditorComponent()) instead of direct column API Column#setEditorComponent().

See the example:

@Autowired
private UiComponents uiComponents;

@ViewComponent
private DataGrid<User> editableUserTable;

@Subscribe
public void onInit(InitEvent event) {
    DataGridEditor<User> editor = editableUserTable.getEditor(); (1)

    editor.setColumnEditorComponent("timeZoneId", generationContext -> {
        //noinspection unchecked
        JmixComboBox<String> timeZoneField = uiComponents.create(JmixComboBox.class); (2)
        timeZoneField.setItems(List.of(TimeZone.getAvailableIDs()));
        timeZoneField.setValueSource(generationContext.getValueSourceProvider().getValueSource("timeZoneId"));
        timeZoneField.setWidthFull();
        timeZoneField.setClearButtonVisible(true);
        timeZoneField.setRequired(true);
        //noinspection unchecked,rawtypes
        timeZoneField.setStatusChangeHandler(((Consumer) generationContext.getStatusHandler())); (3)

        return timeZoneField; (4)
    });
}
1 Get the instance of DataGridEditor.
2 The JmixComboBox component instance is created using the UiComponents factory.
3 Set StatusChangeHandler.
4 The setColumnEditorComponent() method returns the visual component to be shown as the column editor component.

SupportsStatusChangeHandler

By default, field components (for example, textField, comboBox) display error messages in a label above them. Such behaviour has disadvantages in case of limited area of edit cell. The io.jmix.flowui.component.SupportsStatusChangeHandler interface enables to define different way of displaying error messages. Components that implement this interface support error handling delegation.

By default, the inline editor uses StatusChangeHandler to set error message of a component as its title.

Double-click Editing

Sometimes it is necessary to open the inline editor by double-clicking. See the example:

<dataGrid width="100%" dataContainer="usersDc" id="dblClickTable">
    <columns>
        <column property="username"/>
        <column property="firstName" editable="true"/>
        <column property="lastName" editable="true"/>
        <column property="active" editable="true"/>
        <column property="onboardingStatus"/>
    </columns>
</dataGrid>
@ViewComponent
private DataGrid<User> dblClickTable;

@Subscribe
public void onInit(InitEvent event) {
    DataGridEditor<User> tableEditor = dblClickTable.getEditor();
    dblClickTable.addItemDoubleClickListener(e -> {
        tableEditor.editItem(e.getItem());
        Component editorComponent = e.getColumn().getEditorComponent();
        if (editorComponent instanceof Focusable) {
            ((Focusable) editorComponent).focus();
        }
    });
}

Attributes

allRowsVisible

If the allRowsVisible attribute is set to true, the data grid’s height is defined by its rows. All items are fetched from the DataProvider, and dataGrid shows no vertical scroll bar.

allRowsVisible = true disables the data grid’s virtual scrolling so that all the rows are rendered in the DOM at once. If the data grid has a large number of items, using the feature is discouraged to avoid performance issues.

columnReorderingAllowed

dataGrid provides the drag-and-drop functionality allowing users to change the order in which columns are displayed within the data grid.

The column reordering functionality is disabled by default. To enable it, set the columnReorderingAllowed attribute to true.

The column order changes can be tracked with ColumnReorderEvent.

detailsVisibleOnClick

Sets whether the item details can be opened and closed by clicking the rows or not.

dropMode

Sets the drop mode of this drop target. When set to not null, dataGrid fires drop events upon data drop over the data grid or the data grid rows.

Four different drop modes are supported: BETWEEN, ON_TOP, ON_TOP_OR_BETWEEN, and ON_GRID.

editorBuffered

Sets the Editor buffered mode. When the editor is in buffered mode, changes are only committed when the user clicks the save button. In unbuffered mode valid changes are automatically committed.

nestedNullBehavior

Sets the behavior when parsing nested properties which may contain null values in the property chain.

pageSize

Sets the page size, which is the number of items fetched at a time from the data provider. See the com.vaadin.flow.component.grid.Grid.setPageSize() method.

Default is 50.

rowDraggable

Sets whether the user can drag the grid rows or not.

selectionMode

Sets the data grid’s selection mode.

Two different selection modes are supported: SINGLE, and MULTI. Single selection mode is enabled by default.

Handlers

To generate a handler stub in Jmix Studio, use the Handlers tab of the Jmix UI inspector panel or the Generate Handler action available in the top panel of the view class and through the CodeGenerate menu (Alt+Insert / Cmd+N).

CellFocusEvent

com.vaadin.flow.component.grid.CellFocusEvent fired when a cell in the data grid is focused. Corresponds to the grid-cell-focus DOM event.

ColumnReorderEvent

com.vaadin.flow.component.grid.ColumnReorderEvent fired when the columns in the data grid are reordered. Corresponds to the column-reorder-all-columns DOM event.

ColumnResizeEvent

com.vaadin.flow.component.grid.ColumnResizeEvent fired when a data grid column is resized by the user. Corresponds to the column-drag-resize DOM event.

GridDragEndEvent

com.vaadin.flow.component.grid.dnd.GridDragEndEvent - drag end event of dataGrid rows. Corresponds to the grid-dragend DOM event.

GridDragStartEvent

com.vaadin.flow.component.grid.dnd.GridDragStartEvent - drag start event of dataGrid rows. Corresponds to the grid-dragstart DOM event.

GridDropEvent

com.vaadin.flow.component.grid.dnd.GridDropEvent - drop event that occurs on the data grid or its rows. Corresponds to the grid-drop DOM event.

ItemClickEvent

com.vaadin.flow.component.grid.ItemClickEvent fired when a data grid item is clicked. Corresponds to the item-click DOM event.

ItemDoubleClickEvent

com.vaadin.flow.component.grid.ItemDoubleClickEvent fired when a data grid item is double-clicked. Corresponds to the item-double-click DOM event.

SortEvent

com.vaadin.flow.data.event.SortEvent - event describing a change in sorting of a DataProvider. Fired by SortNotifiers.

classNameGenerator

classNameGenerator is used for generating CSS class names for all the cells in the rows in this data grid.

dataGenerator

Adds a data generator for the data grid. If the generator was already added, does nothing. See the com.vaadin.flow.data.provider.HasDataGenerators interface.

dragFilter

Sets the drag filter for this drag source. When the rowDraggable = true, by default all the visible rows can be dragged. A drag filter function can be used to specify the rows that are available for dragging. The function receives an item and returns true if the row can be dragged, false otherwise. See com.vaadin.flow.component.grid.Grid.

dropFilter

Sets the drop filter for this drag target.

When the drop mode of the grid has been set to one of BETWEEN, ON_TOP or ON_TOP_OR_BETWEEN, by default all the visible rows can be dropped over. A drop filter function can be used to specify the rows that are available for dropping over. The function receives an item and should return true if the row can be dropped over, otherwise. See com.vaadin.flow.component.grid.Grid.

Elements

See Also

See the Vaadin Docs for more information.