3.5.2.1.11. DataGrid

In this section:

DataGrid, similarly to the Table component, is designed to display and sort tabular data, and provides means to manipulate rows and columns with greater performance due to lazy loading of data while scrolling.

gui dataGrid 1

XML name of the component: dataGrid.

An example of component definition in an XML-descriptor of a screen:

<data>
    <collection id="ordersDc" class="com.company.sales.entity.Order" view="order-with-customer">
        <loader id="ordersDl">
            <query>
                <![CDATA[select e from sales_Order e order by e.date]]>
            </query>
        </loader>
    </collection>
</data>
<layout>
    <dataGrid id="ordersDataGrid" dataContainer="ordersDc" height="100%" width="100%">
        <columns>
            <column id="date" property="date"/>
            <column id="customer" property="customer.name"/>
            <column id="amount" property="amount"/>
        </columns>
    </dataGrid>
</layout>

In the example above the id attribute is a column identifier, and the property is the name of the entity attribute from the data container that populates the column with data.

If you need to define a data source programmatically in the screen controller, use the metaClass attribute in XML instead of declarative setting a dataContainer.

dataGrid elements

  • columns - an element that defines the DataGrid columns set. If not specified, columns will be automatically determined from the attributes from the view that is defined in dataContainer. Element columns has the following attributes:

    • includeAll – load all the attributes from the view that is defined in dataContainer.

      In the example below, we will show all the attributes from the view used in the customersDc. If the view contains system properties, they will be shown too.

      <dataGrid id="dataGrid"
                width="100%"
                height="100%"
                dataContainer="customersDc">
          <columns includeAll="true"/>
      </dataGrid>

      If the view of the entity contains a reference attribute, this attribute will be displayed according to its instance name. If you want to show a specific attribute, it must be defined in the view as well as in the column element:

      <columns includeAll="true">
          <column id="address.street"/>
      </columns>

      If no view is specified, includeAll attribute will load all the attributes from a given entity and its ancestors.

    • exclude – comma-separated list of attributes that should not be loaded to the DataGrid.

      In the example below, we will show all the attributes excluding name and order:

      <dataGrid id="dataGrid"
                width="100%"
                height="100%"
                dataContainer="customersDc">
          <columns includeAll="true"
                   exclude="name, order"/>
      </dataGrid>

    Each column is described in the nested column element with the following attributes:

    • id - an optional attribute with the column identifier. If not set, the string with the property value will be used as the column identifier. In this case setting the property value is mandatory, otherwise the GuiDevelopmentException exception will be thrown. The id attribute is still mandatory for the columns created in the screen controller.

    • property - contains the entity attribute’s name. Can be either an attribute of the entity from the data source / data container or a linked entity – object graph traversal is indicated with a dot. For example:

      <columns>
          <column id="date" property="date"/>
          <column id="customer" property="customer"/>
          <column id="customerName" property="customer.name"/>
          <column id="customerCountry" property="customer.address.country"/>
      </columns>
    • caption - an optional attribute containing the column caption. If not specified, a localized attribute name will be displayed.

    • expandRatio - sets the column width ratio. By default, all columns have equal width (i.e. expandRatio = 1). If another value is set for at least one column, all implicit values are ignored, and only set values are considered.

    • collapsible - defines whether a user can hide or show columns using the sidebar menu in the top right of DataGrid. The default value is true.

    • collapsed - an optional attribute; hides the column by default when set to true. The default value is false.

    • collapsingToggleCaption - sets the column’s caption in the sidebar menu. By default, its value is null, in this case the caption remains the same as the column’s caption.

      gui dataGrid 2
    • resizable - defines whether a user can change the column’s size.

    • sortable - an optional attribute to disable sorting of the column. Takes effect if the whole DataGrid has sortable attribute set to true (which is by default).

    • width - an optional attribute controlling default column width. May contain only numeric values in pixels.

    • minimumWidth - sets the minimal column width in pixels.

    • maximumWidth - sets the maximal column width in pixels.

    The column element may contain a nested formatter element that allows you to represent the attribute value in a format different from the standard for this DataType:

    <column id="date" property="date">
        <formatter class="com.haulmont.cuba.gui.components.formatters.DateFormatter"
                   format="yyyy-MM-dd HH:mm:ss"
                   useUserTimezone="true"/>
    </column>
  • actions - optional element to define actions for DataGrid. Besides custom actions, the standard actions from the ListActionType enumeration are also supported: create, edit, remove, refresh, add, exclude.

  • buttonsPanel - creates a ButtonsPanel container with action buttons above the DataGrid component.

  • rowsCount - optional element that creates a RowsCount component for the DataGrid. RowsCount enables pagination of data, the page size is set by limitation of records in the data loader with the help of CollectionLoader.setMaxResults() method from the screen controller. Another way to do this is to use a universal Filter component bound with the same data container as the DataGrid.

    The RowsCount component can also display the total number of records returned by current data request without loading these records. When a user clicks the "?" button, it calls the com.haulmont.cuba.core.global.DataManager#getCount method that passes to the database a request with the same parameters as current but with COUNT(*) aggregation function instead of getting results. The returned number is displayed in place of "?" symbol.

    The autoLoad attribute of the RowsCount component set to true enables loading rows count automatically. It can be set in the XML descriptor:

    <rowsCount autoLoad="true"/>

    Also, this behavior can be enabled or disabled via RowsCount API in the screen controller:

    boolean autoLoadEnabled = rowsCount.getAutoLoad();
    rowsCount.setAutoLoad(false);
dataGrid attributes
  • The aggregatable attribute enables aggregation for DataGrid rows. The following operations are supported:

    • SUM − calculate the sum

    • AVG − find the average value

    • COUNT − calculate the total number

    • MIN − find the minimum value

    • MAX − find the maximum value

    The aggregation element should be set for aggregated DataGrid columns with the type attribute, which sets the aggregation function. By default, only numeric data types are supported in aggregated columns, such as Integer, Double, Long, and BigDecimal. The aggregated values are shown in an additional row at the top of the DataGrid. The functionality of aggregation is the same as for Table component. It means that you can use strategyClass, valueDescription, and formatter for the aggregation.

    An example of an aggregated DataGrid description:

    <dataGrid id="ordersDataGrid"
              dataContainer="ordersDc"
              aggregationPosition="BOTTOM"
              aggregatable="true">
        <columns>
            <column id="customerGrade" property="customer.grade">
                <aggregation strategyClass="com.company.sample.CustomerGradeAggregation"
                             valueDescription="msg://customerGradeAggregationDesc"/>
            </column>
            <column id="amount" property="amount">
                <aggregation type="SUM">
                    <formatter class="com.company.sample.MyFormatter"/>
                </aggregation>
            </column>
            ...
        </columns>
        ...
    </dataGrid>
  • The aggregationPosition attribute allows you to specify the location of the aggregation row: TOP or BOTTOM. TOP is used by default.

  • columnResizeMode - sets the mode of columns resizing by user. Two modes are supported:

    • ANIMATED - the columns size follows the mouse when dragging (default mode).

    • SIMPLE - the columns size is changed after the dragging is finished.

    The column size changes can be tracked with ColumnResizeListener. The origin of the column size changes event can be tracked using isUserOriginated() method.

  • columnsCollapsingAllowed - defines whether a user can hide columns in the sidebar menu. Displayed columns are checked in the menu. There are additional menu items:

    • Select all − shows all columns;

    • Deselect all − hides all columns.

      gui dataGrid 16

      When a column name is checked/unchecked, the value of collapsed attribute of each column is updated. When set to false, the collapsed attribute of any column cannot be set to true.

      The column collapsing changes can be tracked with ColumnCollapsingChangeListener. The origin of the column collapsing event can be tracked using isUserOriginated() method.

  • contextMenuEnabled - enables turning on and off the context menu. Default value is true.

    The right mouse clicks on the DataGrid can be tracked with ContextClickListener.

  • editorBuffered - sets the buffered editor mode. The default mode is buffered (true).

  • editorCancelCaption - sets the caption on the cancel button in the DataGrid editor.

  • editorCrossFieldValidate - enables cross field validation in the inline editor. Default value is true.

  • editorEnabled - enables the item inline editor UI. Default value is false. If dataGrid is bound to KeyValueCollectionContainer, it is supposed to be read-only, and editorEnabled attribute becomes nonsense.

  • editorSaveCaption - sets the caption on the save button in the DataGrid inline editor.

  • frozenColumnCount - sets the number of fixed DataGrid columns. The 0 value means that no columns will be fixed except the predefined column with checkboxes for multiple choice if the multiselect mode is used. The -1 value makes even multiselect column not fixed.

  • headerVisible - defines if the DataGrid header is visible. The default value is true.

  • htmlSanitizerEnabled - enables or disables HTML sanitization. The DataGrid component has some providers that can render HTML:

    • HtmlRenderer

    • RowDescriptionProvider with ContentMode.HTML

    • DescriptionProvider with ContentMode.HTML

      The result of the execution of these providers is sanitized if htmlSanitizerEnabled attribute is set to true for DataGrid component.

      protected static final String UNSAFE_HTML = "<i>Jackdaws </i><u>love</u> <font size=\"javascript:alert(1)\" " +
                  "color=\"moccasin\">my</font> " +
                  "<font size=\"7\">big</font> <sup>sphinx</sup> " +
                  "<font face=\"Verdana\">of</font> <span style=\"background-color: " +
                  "red;\">quartz</span><svg/onload=alert(\"XSS\")>";
      
      @Inject
      private DataGrid<Customer> customersDataGrid;
      @Inject
      private DataGrid<Customer> customersDataGrid2;
      @Inject
      private DataGrid<Customer> customersDataGrid3;
      
      @Subscribe
      public void onInit(InitEvent event) {
          customersDataGrid.setHtmlSanitizerEnabled(true);
          customersDataGrid.getColumn("name")
                  .setRenderer(customersDataGrid.createRenderer(DataGrid.HtmlRenderer.class));
      
          customersDataGrid2.setHtmlSanitizerEnabled(true);
          customersDataGrid2.setRowDescriptionProvider(customer -> UNSAFE_HTML, ContentMode.HTML);
      
          customersDataGrid3.setHtmlSanitizerEnabled(true);
          customersDataGrid3.getColumn("name").setDescriptionProvider(customer -> UNSAFE_HTML, ContentMode.HTML);
      }

      The htmlSanitizerEnabled attribute overrides the value of global cuba.web.htmlSanitizerEnabled configuration property.

      If you want to use HtmlRenderer with custom presentationProvider, then the presentation value will not be sanitized by default. If you want sanitize presentation value you have to do it yourself:

      protected static final String UNSAFE_HTML = "<i>Jackdaws </i><u>love</u> <font size=\"javascript:alert(1)\" " +
                  "color=\"moccasin\">my</font> " +
                  "<font size=\"7\">big</font> <sup>sphinx</sup> " +
                  "<font face=\"Verdana\">of</font> <span style=\"background-color: " +
                  "red;\">quartz</span><svg/onload=alert(\"XSS\")>";
      
      @Inject
      private DataGrid<Customer> customersDataGrid;
      
      @Inject
      private HtmlSanitizer htmlSanitizer;
      
      @Subscribe
      public void onInit(InitEvent event) {
          customersDataGrid.getColumn("name")
                  .setRenderer(customersDataGrid.createRenderer(DataGrid.HtmlRenderer.class),
                          (Function<String, String>) nameValue -> htmlSanitizer.sanitize(UNSAFE_HTML));
      }
  • reorderingAllowed - defines whether a user can change the columns order by dragging them with a mouse. The default value is true.

    The column order changes can be tracked with ColumnReorderListener. The origin of the order change event can be tracked using isUserOriginated() method.

  • selectionMode - sets the rows selection mode. There are 4 predefined selection modes:

    • SINGLE - single record selection.

    • MULTI - multiple selection as in any table.

    • MULTI_CHECK - multiple selection using the embedded column with checkboxes.

    • NONE - selection is disabled.

      Rows selection events can be tracked by SelectionListener. The origin of the selection event can be tracked using isUserOriginated() method.

      gui dataGrid 3
  • sortable - enables or disables the DataGrid sorting. The default value is true. When the sorting is enabled, the click on the column name will display the sorting icon to the right of the column caption. Sorting of any specific column can be disabled by this column’s sortable attribute.

    The DataGrid sorting events can be tracked by SortListener. The origin of the sorting event can be tracked using isUserOriginated() method.

  • textSelectionEnabled - enables or disables text selection in the DataGrid cells. The default value is false.

Methods of the DataGrid interface

  • getColumns() - returns the current set of DataGrid columns in their current display order.

  • getSelected(), getSingleSelected() - return instances of the entities corresponding to the selected rows of the table. A collection can be obtained by invoking getSelected(). If nothing is selected, the application returns an empty set. If SelectionMode.SINGLE is set, it is more convenient to use getSingleSelected() method returning one selected entity or null, if nothing is selected.

  • getVisibleColumns() - returns the current set of visible DataGrid columns in their current display order.

  • scrollTo() - method allows you to scroll the DataGrid to the specified row. It takes an entity instance identifying the row as a parameter. Besides the entity instance, an overloaded method can take a ScrollDestination parameter with the following possible values:

    • ANY - scroll as little as possible to show the required record.

    • START - scroll to place the required record in the beginning of the DataGrid visible area.

    • MIDDLE - scroll to place the required record in the centre of the DataGrid visible area.

    • END - scroll to place the required record in the end of the DataGrid visible area.

  • scrollToStart() and scrollToEnd() - scroll the DataGrid to the top and to the end respectively.

  • addCellStyleProvider() - adds style provider for the DataGrid cells.

  • addRowStyleProvider() - adds style provider for the DataGrid rows.

  • setEnterPressAction() - method allows you to define an action executed when Enter is pressed. If such action is not defined, the table will attempt to find an appropriate one in the list of its actions in the following order:

    • The action defined by the setItemClickAction() method.

    • The action assigned to the Enter key by the shortcut property.

    • The edit action.

    • The view action.

    If such action is found, and has enabled = true property, the action is executed.

  • setItemClickAction() - method allows you to define an action that will be performed when a table row is double-clicked. If such action is not defined, the table will attempt to find an appropriate one in the list of its actions in the following order:

    • The action assigned to the Enter key by the shortcut property.

    • The edit action.

    • The view action.

    If such action is found, and has enabled = true property, the action is executed.

    Item click events can be tracked with ItemClickListener.

  • sort() - sorts the data for the specified column in the sort direction chosen from 2 values of the SortDirection enum:

    • ASCENDING - ascending (e.g. A-Z, 1..9) sort order.

    • DESCENDING - descending (e.g. Z-A, 9..1) sort order.

  • The getAggregationResults() method returns a map with aggregation results, where map keys are DataGrid column identifiers, and values are aggregation values.

Usage of description providers

  • setDescriptionProvider() method is used to generate optional descriptions (tooltips) for the cells of individual DataGrid columns. The description may contain HTML markup.

    @Inject
    private DataGrid<Customer> customersDataGrid;
    
    @Subscribe
    protected void onInit(InitEvent event) {
        customersDataGrid.getColumnNN("age").setDescriptionProvider(customer ->
                        getPropertyCaption(customer, "age") +
                                customer.getAge(),
                ContentMode.HTML);
    
        customersDataGrid.getColumnNN("active").setDescriptionProvider(customer ->
                        getPropertyCaption(customer, "active") +
                                getMessage(customer.getActive() ? "trueString" : "falseString"),
                ContentMode.HTML);
    
        customersDataGrid.getColumnNN("grade").setDescriptionProvider(customer ->
                        getPropertyCaption(customer, "grade") +
                                messages.getMessage(customer.getGrade()),
                ContentMode.HTML);
    }
    gui dataGrid 11
  • setRowDescriptionProvider() method is used to generate optional descriptions (tooltips) for DataGrid rows. If a column description provider is also set, the row description generated by provider is used for cells for which the cell description provider returns null.

    customersDataGrid.setRowDescriptionProvider(Instance::getInstanceName);
    gui dataGrid 10

Usage of the DetailsGenerator interface

The DetailsGenerator interface allows you to create a custom component to display the details of a particular row using the setDetailsGenerator() method:

@Inject
private DataGrid<Order> ordersDataGrid;
@Inject
private UiComponents uiComponents;

@Install(to = "ordersDataGrid", subject = "detailsGenerator")
protected Component ordersDataGridDetailsGenerator(Order order) {
    VBoxLayout mainLayout = uiComponents.create(VBoxLayout.NAME);
    mainLayout.setWidth("100%");
    mainLayout.setMargin(true);

    HBoxLayout headerBox = uiComponents.create(HBoxLayout.NAME);
    headerBox.setWidth("100%");

    Label infoLabel = uiComponents.create(Label.NAME);
    infoLabel.setHtmlEnabled(true);
    infoLabel.setStyleName("h1");
    infoLabel.setValue("Order info:");

    Component closeButton = createCloseButton(order);
    headerBox.add(infoLabel);
    headerBox.add(closeButton);
    headerBox.expand(infoLabel);

    Component content = getContent(order);

    mainLayout.add(headerBox);
    mainLayout.add(content);
    mainLayout.expand(content);

    return mainLayout;
}

private Component createCloseButton(Order entity) {
    Button closeButton = uiComponents.create(Button.class);
    // ... (1)
    return closeButton;
}

private Component getContent(Order entity) {
    Label<String> content = uiComponents.create(Label.TYPE_STRING);
    content.setHtmlEnabled(true);
    StringBuilder sb = new StringBuilder();
    // ... (2)
    content.setValue(sb.toString());
    return content;
}
1 – See the full code of the createCloseButton method in the DataGridDetailsGeneratorSample class.
2 – See the full code of the getContent method in the DataGridDetailsGeneratorSample class.

Result:

gui dataGrid 15

Usage of DataGrid inline editor

The DataGrid component has an API for inline editing of records in the cells. When an item is being edited, the inline edit UI with default save and cancel buttons is displayed.

Methods of inline editor API:

  • getEditedItem() - returns the item that is currently being edited.

  • isEditorActive() - returns whether an item is currently being edited in the editor.

  • editItem(Object itemId) (Deprecated) - opens the editor interface for the provided item id. Scrolls the Grid to bring the item to view if it is not already visible.

  • edit(Entity item) - opens the editor interface for the provided item. Scrolls the Grid to bring the item to view if it is not already visible.

DataGrid inline editor can take into account entity constraints (cross field validation). If there are validation errors, DataGrid will show an error message. To enable/disable validation or get current state use the following methods:

  • setEditorCrossFieldValidate(boolean validate) - enables or disables the cross field validation in the inline editor. The default value is true.

  • isEditorCrossFieldValidate() - return true if the inline editor validates cross field rules.

You can add and remove listeners to the editor using the following methods:

  • addEditorOpenListener(), removeEditorOpenListener() - DataGrid editor open listener.

    This listener is triggered by a double click on the DataGrid area that instantiates the inline editor and enables to get the fields of the edited row. This enables to update some fields depending on other fields' values without closing the editor.

    For example:

    customersTable.addEditorOpenListener(editorOpenEvent -> {
        Map<String, Field> fieldMap = editorOpenEvent.getFields();
        Field active = fieldMap.get("active");
        Field grade = fieldMap.get("grade");
    
        ValueChangeListener listener = e ->
                active.setValue(true);
        grade.addValueChangeListener(listener);
    });
  • addEditorCloseListener(), removeEditorCloseListener() - DataGrid editor close listener.

  • addEditorPreCommitListener(), removeEditorPreCommitListener() - DataGrid editor pre commit listener.

  • addEditorPostCommitListener(), removeEditorPostCommitListener() - DataGrid editor post commit listener.

The changes are committed to the data source or data container only. The logic to save these changes in the database should be added separately.

The editor field can be customized with the help of EditorFieldGenerationContext class. Apply the setEditFieldGenerator() method to a column in order to set a custom component for editing this column:

@Inject
private DataGrid<Order> ordersDataGrid;
@Inject
private UiComponents uiComponents;

@Subscribe
protected void onInit(InitEvent event) {
    ordersDataGrid.getColumnNN("amount").setEditFieldGenerator(orderEditorFieldGenerationContext -> {
        LookupField<BigDecimal> lookupField = uiComponents.create(LookupField.NAME);
        lookupField.setValueSource((ValueSource<BigDecimal>) orderEditorFieldGenerationContext
                .getValueSourceProvider().getValueSource("amount"));
        lookupField.setOptionsList(Arrays.asList(BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.TEN));

        return lookupField;
    });
}

The result:

gui dataGrid 14

Usage of the ColumnGenerator interface

DataGrid enables adding generated columns. There are two ways to create a generated column:

  • Declaratively using the @Install annotation in the screen controller:

    @Inject
    private UiComponents uiComponents;
    
    @Install(to = "dataGrid.fullName", subject = "columnGenerator")
    protected Component fullNameColumnGenerator(DataGrid.ColumnGeneratorEvent<Customer> e) {
        Label<String> label = uiComponents.create(Label.TYPE_STRING);
        label.setValue(e.getItem().getFirstName() + " " + e.getItem().getLastName());
        return label;
    }

    ColumnGeneratorEvent contains information on the entity, displayed in the current DataGrid row, and the column identifier.

  • Programmatically with the help of the methods:

    • addGeneratedColumn(String columnId, ColumnGenerator generator)

    • addGeneratedColumn(String columnId, ColumnGenerator generator, int index)

    ColumnGenerator is a special interface that defines the generated, or calculated, column:

    • value of each column’s row,

    • the type of value - common for the whole column.

    Below is an example of generating a column that displays users' login in the upper case:

    @Subscribe
    protected void onInit(InitEvent event) {
        DataGrid.Column column = usersGrid.addGeneratedColumn("loginUpperCase", new DataGrid.ColumnGenerator<User, String>(){
            @Override
            public String getValue(DataGrid.ColumnGeneratorEvent<User> event){
                return event.getItem().getLogin().toUpperCase();
            }
    
            @Override
            public Class<String> getType(){
                return String.class;
            }
        }, 1);
        column.setCaption("Login Upper Case");
    }

    The result:

    gui dataGrid 7

    By default, the generated column is added to the end of the table. There are two possible ways to manage the column’s position: either using an index in the code or adding a column in advance in the XML descriptor and pass its id to the addGeneratedColumn method.

Usage of renderers

The way the data is displayed in columns can be customized using parameterized declarative renderers. Some DataGrid renderers are set by special XML elements with parameters defined in the corresponding attributes. Renderers can be declared for not generated columns.

The list of renderers supported by the platform:

  • ButtonRenderer – displays string values as a button caption.

    The ButtonRenderer cannot be declared in the XML descriptor because it is not possible to define a renderer click listener in the XML descriptor. Studio will generate the ButtonRenderer declaration code in the init() screen controller method:

    @Inject
    private DataGrid<Customer> customersDataGrid;
    
    @Inject
    private Notifications notifications;
    
    @Subscribe
    public void onInit(InitEvent event) {
        DataGrid.ButtonRenderer<Customer> customersDataGridNameRenderer =
                    customersDataGrid.createRenderer(DataGrid.ButtonRenderer.class);
        customersDataGridNameRenderer.setRendererClickListener(clickableButtonRendererClickEvent ->
            {
                notifications.create()
                    .withType(Notifications.NotificationType.TRAY)
                    .withCaption("ButtonRenderer")
                    .withDescription("Column id: " + clickableButtonRendererClickEvent.getColumnId())
                    .show();
            });
        customersDataGrid.getColumn("name").setRenderer(customersDataGridNameRenderer);
    }
  • CheckBoxRenderer – displays boolean values as a checkbox icon.

    The column element of DataGrid has a child checkBoxRenderer element:

    <column property="checkBoxRenderer" id="checkBoxRendererColumn">
        <checkBoxRenderer/>
    </column>
  • ClickableTextRenderer – displays simple plain-text string values as a link with call back handler.

    The ClickableTextRenderer cannot be declared in the XML descriptor because it is not possible to define a renderer click listener in the XML descriptor. Studio will generate the ClickableTextRenderer declaration code in the init() screen controller method:

    @Inject
    private DataGrid<Customer> customersDataGrid;
    
    @Inject
    private Notifications notifications;
    
    @Subscribe
    public void onInit(InitEvent event) {
        DataGrid.ClickableTextRenderer<Customer> customersDataGridNameRenderer =
                    customersDataGrid.createRenderer(DataGrid.ClickableTextRenderer.class);
        customersDataGridNameRenderer.setRendererClickListener(clickableTextRendererClickEvent -> {
            notifications.create()
                    .withType(Notifications.NotificationType.TRAY)
                    .withCaption("ClickableTextRenderer")
                    .withDescription("Column id: " + clickableTextRendererClickEvent.getColumnId())
                    .show();
        });
        customersDataGrid.getColumn("name").setRenderer(customersDataGridNameRenderer);
    }
  • ComponentRenderer – a renderer for UI components.

    The column element of DataGrid has a child componentRenderer element:

    <column property="componentRenderer" id="componentRendererColumn">
        <componentRenderer/>
    </column>
  • DateRenderer – displays dates in the defined format.

    The column element of DataGrid has a child dateRenderer element with non-required nullRepresentation attribute and required format string attribute:

    <column property="dateRenderer" id="dateRendererColumn">
        <dateRenderer nullRepresentation="null" format="yyyy-MM-dd HH:mm:ss"/>
    </column>
  • IconRenderer – a renderer that represents CubaIcon.

    The column element of DataGrid has a child iconRenderer element.

    Below is an example of rendering an entity attribute with the String type as CubaIcon:

    <column id="iconOS" property="iconOS">
        <iconRenderer/>
    </column>
    @Install(to = "devicesTable.iconOS", subject = "columnGenerator")
    private Icons.Icon devicesTableIconOSColumnGenerator(DataGrid.ColumnGeneratorEvent<Device> event) {
        return CubaIcon.valueOf(event.getItem().getIconOS());
    }

    The result:

    gui dataGrid iconColumn
  • ImageRenderer – uses the path to an image to display the image.

    The ImageRenderer cannot be declared in the XML descriptor because it is not possible to define a renderer click listener in the XML descriptor. Studio will generate the ImageRenderer declaration code in the init() screen controller method:

    @Inject
    private DataGrid<TestEntity> testEntitiesDataGrid;
    @Inject
    private Notifications notifications;
    
    @Subscribe
    public void onInit(InitEvent event) {
        DataGrid.ImageRenderer<TestEntity> imageRenderer =
                testEntitiesDataGrid.createRenderer(DataGrid.ImageRenderer.class);
        imageRenderer.setRendererClickListener(imageRendererClickEvent -> notifications.create()
                .withType(Notifications.NotificationType.TRAY)
                .withCaption("ImageRenderer")
                .withDescription("Column id: " + imageRendererClickEvent.getColumnId())
                .show());
        testEntitiesDataGrid.getColumn("imageRendererColumn").setRenderer(imageRenderer);
    }
  • HtmlRenderer – displays HTML layout.

    The column element of DataGrid has a child htmlRenderer element with non-required nullRepresentation attribute:

    <column property="htmlRenderer" id="htmlRendererColumn">
        <htmlRenderer nullRepresentation="null"/>
    </column>
  • LocalDateRenderer – displays dates as LocalDate values.

    The column element of DataGrid has a child localDateRenderer element with non-required nullRepresentation attribute and required format string attribute:

    <column property="localDateRenderer" id="localDateRendererColumn">
        <localDateRenderer nullRepresentation="null" format="dd/MM/YYYY"/>
    </column>
  • LocalDateTimeRenderer – displays dates as LocalDateTime values.

    The column element of DataGrid has a child localDateTimeRenderer element with non-required nullRepresentation attribute and required format string attribute:

    <column property="localDateTimeRenderer" id="localDateTimeRendererColumn">
        <localDateTimeRenderer nullRepresentation="null" format="dd/MM/YYYY HH:mm:ss"/>
    </column>
  • NumberRenderer – displays numbers in the defined format.

    The column element of DataGrid has a child numberRenderer element with non-required nullRepresentation attribute and required format string attribute:

    <column property="numberRenderer" id="numberRendererColumn">
        <numberRenderer nullRepresentation="null" format="%f"/>
    </column>
  • ProgressBarRenderer – displays double values between 0 and 1 as a ProgressBar component.

    The column element of DataGrid has a child progressBarRenderer element:

    <column property="progressBar" id="progressBarColumn">
        <progressBarRenderer/>
    </column>
  • TextRenderer – displays plain text.

    The column element of DataGrid has a child textRenderer element with non-required nullRepresentation attribute:

    <column property="textRenderer" id="textRendererColumn">
        <textRenderer nullRepresentation="null"/>
    </column>

The WebComponentRenderer interface allows you to display components of different web components types in the DataGrid cells. This interface is implemented only in the Web Module. Below is an example of creating a column with the LookupField component:

@Inject
private DataGrid<User> usersGrid;
@Inject
private UiComponents uiComponents;
@Inject
private Configuration configuration;
@Inject
private Messages messages;

@Subscribe
protected void onInit(InitEvent event) {
    Map<String, Locale> locales = configuration.getConfig(GlobalConfig.class).getAvailableLocales();
    Map<String, String> options = new TreeMap<>();
    for (Map.Entry<String, Locale> entry : locales.entrySet()) {
        options.put(entry.getKey(), messages.getTools().localeToString(entry.getValue()));
    }

    DataGrid.Column column = usersGrid.addGeneratedColumn("language",
            new DataGrid.ColumnGenerator<User, Component>() {
                @Override
                public Component getValue(DataGrid.ColumnGeneratorEvent<User> event) {
                    LookupField<String> component = uiComponents.create(LookupField.NAME);
                    component.setOptionsMap(options);
                    component.setWidth("100%");

                    User user = event.getItem();
                    component.setValue(user.getLanguage());

                    component.addValueChangeListener(e -> user.setLanguage(e.getValue()));

                    return component;
                }

                @Override
                public Class<Component> getType() {
                    return Component.class;
                }
            });

    column.setRenderer(new WebComponentRenderer());
}

The result:

gui dataGrid 13

When the field type does not match the data type that can be processed by a renderer, one can create a Function to match data types of the model and the view. For example, to display a boolean value as an icon, it would be handy to use the HtmlRenderer to display HTML layout and implement the logic to convert a boolean value to the layout for icons' display.

@Inject
private DataGrid<User> usersGrid;

@Subscribe
protected void onInit(InitEvent event) {

    DataGrid.Column<User> hasEmail = usersGrid.addGeneratedColumn("hasEmail", new DataGrid.ColumnGenerator<User, Boolean>() {
        @Override
        public Boolean getValue(DataGrid.ColumnGeneratorEvent<User> event) {
            return StringUtils.isNotEmpty(event.getItem().getEmail());
        }

        @Override
        public Class<Boolean> getType() {
            return Boolean.class;
        }
    });

    hasEmail.setCaption("Has Email");
    hasEmail.setRenderer(
        usersGrid.createRenderer(DataGrid.HtmlRenderer.class),
        (Function<Boolean, String>) hasEmailValue -> {
            return BooleanUtils.isTrue(hasEmailValue)
                    ? FontAwesome.PLUS_SQUARE.getHtml()
                    : FontAwesome.MINUS_SQUARE.getHtml();
        });
}

The result:

gui dataGrid 9

The renderers can be created in three ways:

  • declaratively using the special elements of the column element of DataGrid.

  • passing a renderer interface to the fabric method of the DataGrid interface. Suits for GUI and Web modules.

  • directly creating a renderer implementation for the corresponding module:

    dataGrid.createRenderer(DataGrid.ImageRenderer.class) → new WebImageRenderer()

    For the moment this way is suitable only for the Web module.

Header and Footer

HeaderRow and FooterRow interfaces are used to represent header and footer cells respectively. They can be a merged cell for multiple columns.

The following methods of DataGrid allow to create and manage the DataGrid header and footer:

  • appendHeaderRow(), appendFooterRow() - adds a new row at the bottom of the header/footer section.

  • prependHeaderRow(), prependFooterRow() - adds a new row at the top of the header/footer section.

  • addHeaderRowAt(), addFooterRowAt() - inserts a new row at the given position to the header/footer section. Shifts the row currently at that position and any subsequent rows down incrementing their indices.

  • removeHeaderRow(), removeFooterRow() - removes the given row from the header/footer section.

  • getHeaderRowCount(), getFooterRowCount() - gets the row count for the header/footer section.

  • setDefaultHeaderRow() - sets the default row of the header. The default row is a special header row providing a user interface for sorting columns.

HeaderCell and FooterCell interfaces provide means of customization of static DataGrid cells:

  • setStyleName() - sets a custom style name for this cell.

  • getCellType() - returns the type of content stored in this cell. There are 3 types of DataGridStaticCellType enumeration available:

    • TEXT

    • HTML

    • COMPONENT

  • getComponent(), getHtml(), getText() - returns the content displayed in this cell depending on its type.

Below is an example of DataGrid the header that contains merged cells, and the footer displaying calculated values.

<dataGrid id="dataGrid" dataContainer="countryGrowthDs" width="100%">
    <columns>
        <column property="country"/>
        <column property="year2017"/>
        <column property="year2018"/>
    </columns>
</dataGrid>
@Inject
private DataGrid<CountryGrowth> dataGrid;
@Inject
private UserSessionSource userSessionSource;
@Inject
private Messages messages;
@Inject
private CollectionContainer<CountryGrowth> countryGrowthsDc;

private DecimalFormat percentFormat;

@Subscribe
protected void onBeforeShow(BeforeShowEvent event) {
    initPercentFormat();
    initHeader();
    initFooter();
    initRenderers();
}

private DecimalFormat initPercentFormat() {
    percentFormat = (DecimalFormat) NumberFormat.getPercentInstance(userSessionSource.getLocale());
    percentFormat.setMultiplier(1);
    percentFormat.setMaximumFractionDigits(2);
    return percentFormat;
}

private void initRenderers() {
    dataGrid.getColumnNN("year2017").setRenderer(new WebNumberRenderer(percentFormat));
    dataGrid.getColumnNN("year2018").setRenderer(new WebNumberRenderer(percentFormat));
}

private void initHeader() {
    DataGrid.HeaderRow headerRow = dataGrid.prependHeaderRow();
    DataGrid.HeaderCell headerCell = headerRow.join("year2017", "year2018");
    headerCell.setText("GDP growth");
    headerCell.setStyleName("center-bold");
}

private void initFooter() {
    DataGrid.FooterRow footerRow = dataGrid.appendFooterRow();
    footerRow.getCell("country").setHtml("<strong>" + messages.getMainMessage("average") + "</strong>");
    footerRow.getCell("year2017").setText(percentFormat.format(getAverage("year2017")));
    footerRow.getCell("year2018").setText(percentFormat.format(getAverage("year2018")));
}

private double getAverage(String propertyId) {
    double average = 0.0;
    List<CountryGrowth> items = countryGrowthsDc.getItems();
    for (CountryGrowth countryGrowth : items) {
        Double value = countryGrowth.getValue(propertyId);
        average += value != null ? value : 0.0;
    }
    return average / items.size();
}
gui dataGrid 12

DataGrid styles

Уou can set predefined styles to the DataGrid component using the stylename attribute in the XML descriptor.

<dataGrid id="dataGrid"
          width="100%"
          height="100%"
          stylename="borderless"
          dataContainer="customersDc">
</dataGrid>

Or set a style programmatically in the screen controller.

dataGrid.setStyleName("borderless");

Predefined styles:

  • borderless - removes the outer border of the DataGrid.

  • no-horizontal-lines - removes the horizontal divider lines between the DataGrid rows.

  • no-vertical-lines - removes the vertical divider lines between the DataGrid columns.

  • no-stripes - removes the alternating row colors.

The appearance of the DataGrid component can be customized using SCSS variables with $cuba-datagrid-* prefix. You can change these variables in the visual editor after creating a theme extension or a custom theme.


Attributes of dataGrid

aggregatable - aggregationPosition - align - caption - captionAsHtml - colspan - columnResizeMode - columnsCollapsingAllowed - contextHelpText - contextHelpTextHtmlEnabled - contextMenuEnabled - css - dataContainer - description - descriptionAsHtml - editorBuffered - editorCancelCaption - editorCrossFieldValidate - editorEnabled - editorSaveCaption - emptyStateLinkMessage - emptyStateMessage - enable - box.expandRatio - frozenColumnCount - headerVisible - height - htmlSanitizerEnabled - icon - id - metaClass - reorderingAllowed - responsive - rowspan - selectionMode - settingsEnabled - sortable - stylename - tabIndex - textSelectionEnabled - visible - width

Elements of dataGrid

actions - buttonsPanel - columns - rowsCount

Attributes of columns

includeAll - exclude

Attributes of column

caption - collapsed - collapsible - collapsingToggleCaption - editable - expandRatio - id - maximumWidth - minimumWidth - property - resizable - sort - sortable - width

Elements of column

aggregation - checkBoxRenderer - componentRenderer - dateRenderer - formatter - iconRenderer - htmlRenderer - localDateRenderer - localDateTimeRenderer - numberRenderer - progressBarRenderer - textRenderer

Attributes of aggregation

strategyClass - type - valueDescription

API

addGeneratedColumn - applySettings - createRenderer - edit - getAggregationResults - saveSettings - getColumns - setDescriptionProvider - addCellStyleProvider - setConverter - setDetailsGenerator - setEditorCrossFieldValidate - setEmptyStateLinkClickHandler - setEnterPressAction - setItemClickAction - setRenderer - setRowDescriptionProvider - addRowStyleProvider - sort

Listeners of dataGrid

ColumnCollapsingChangeListener - ColumnReorderListener - ColumnResizeListener - ContextClickListener - EditorCloseListener - EditorOpenListener - EditorPostCommitListener - EditorPreCommitListener - ItemClickListener - SelectionListener - SortListener

Predefined styles

borderless - no-horizontal-lines - no-vertical-lines - no-stripes