dataGrid 数据网格

基本用法

创建该组件时,在 XML 中声明一个 dataGrid 元素,并与一个 数据容器 绑定。组件支持集合数据容器和键值对数据容器。然后,设置需要在表格中展示的属性:

  • 如需展示 fetch plan 中的所有属性,添加一个带 includeAll = true 属性的 columns 元素即可。排除不需要的属性,可以在 exclude 中以逗号分隔设置。

  • 如需展示部分属性,也可以先添加 columns 元素,然后在其内部为所需的属性添加 column 元素。

  • 如果 fetch plan 包含引用属性,在该属性会显示其 实例名称。如需显示子实体的特定属性,需要在 fetch plan 和 column 元素中都添加子实体属性。

下面的示例演示了 dataGrid 的基本用法:

<data readOnly="true">
    <collection id="usersDc"
                class="com.company.onboarding.entity.User">
        <fetchPlan extends="_base">
            <property name="department">
                <property name="name"/> (1)
            </property>
        </fetchPlan>
        <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">
        <columns>
            <column property="username"/> (2)
            <column property="firstName"/>
            <column property="lastName"/>
            <column property="active"/>
            <column property="onboardingStatus"/>
            <column property="department.name"/> (3)
        </columns>
    </dataGrid>
</layout>
1 引用属性。
2 显示根实体属性的列。
3 显示引用实体属性的列,使用点(".")访问引用属性。
data grid basics

数据绑定

数据绑定是指将可视化组件与数据容器想关联。数据网格可以展示 集合数据容器键值对数据容器 中的数据。

集合容器

典型地,可以在 XML 中使用 dataContainer 属性将数据与 dataGrid 绑定。该属性需要指定一个 集合数据容器,其中包含需要展示的数据。请参考之前小节的 示例

键值对容器

DataGrid 还可以绑定至 键值对容器 展示查询的纯数值和聚合值。示例:

<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>

编程式绑定

如需以编程的方式在视图控制器定义数据容器,则需要设置 metaClass 属性而非 dataContainer

<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>

然后,在视图控制器中,使用 ContainerDataGridItems 类将数据网格和数据容器绑定:

@ViewComponent
private DataGrid<User> dataGrid;

@ViewComponent
private CollectionContainer<User> usersDc;

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

行内编辑

该组件支持行内编辑,用户可以在只读和编辑模式之间切换。行内编辑可以通过 操作列 中的按钮激活,或通过 双击 激活。

行内编辑需要通过显式的保存操作将数据提交至数据库。可以给用户提供一个 "保存" 按钮,或实现 自动保存,当用户离开当前单元格时自动保存改动。

操作列

使用 editorActionsColumn 在每行中提供 EditClose 按钮。用户可以使用这些按钮开始或结束编辑。

操作列会添加在所有列的后面,如果使用了 includeAll="true",操作列可能会在很远的最右边。
data grid editing
显示代码
<dataGrid width="100%" dataContainer="usersDc" id="editableUsersTable">
    <columns>
        <column property="username"/>
        <column property="firstName" editable="true"/> (1)
        <column property="lastName" editable="true"/>
        <column property="active" editable="true"/>
        <column property="onboardingStatus"/>
        <editorActionsColumn>
            <editButton text="Edit" icon="PENCIL"/> (2)
            <closeButton text="Close" icon="CLOSE"/> (3)
        </editorActionsColumn>
    </columns>
</dataGrid>
1 允许某些列 可编辑
2 开始编辑的按钮。
3 完成编辑的按钮。

缓存模式

缓存模式 开启时,用户需要显式的确认或取消正在编辑的内容,以防止误操作。点击不同的表格行,会自动取消编辑。

data grid buffered editor
显示代码
<dataGrid width="100%" dataContainer="usersDc" editorBuffered="true"> (1)
    <columns>
        <column property="username"/>
        <column property="firstName" editable="true"/> (2)
        <column property="lastName" editable="true"/>
        <column property="active" editable="true"/>
        <column property="onboardingStatus"/>
        <editorActionsColumn>
            <editButton text="Edit" icon="PENCIL"/> (3)
            <saveButton icon="CHECK" themeNames="success"/> (4)
            <cancelButton icon="CLOSE" themeNames="error"/> (5)
        </editorActionsColumn>
    </columns>
</dataGrid>
1 启用缓存模式。
2 允许某些列 可编辑
3 开始编辑的按钮。
4 确认编辑的按钮。
5 取消编辑的按钮。

双击编辑

有时候通过双击的方式打开行内编辑器更加方便。

data grid double click editing
显示代码
<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;

@ViewComponent
private GridMenuItem<Object> emailItem;


@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();
        }
    });
}

自动保存改动

包括 dataGrid 在内的可视化组件会将改动的数据暂存在数据容器中,直到有一个确认的操作将数据提交至数据库。

如果需要在用户离开当前单元格时自动保存行内编辑的修改,可以创建一个 ItemPropertyChangeEvent 事件的处理器并通过 dataManager 保存数据:

@Subscribe(id = "usersDc", target = Target.DATA_CONTAINER)
public void onUsersDcItemPropertyChange(final InstanceContainer.ItemPropertyChangeEvent<User> event) {
    dataManager.save(event.getItem());
}

DataGridEditor

io.jmix.flowui.component.grid.editor.DataGridEditor 接口提供了额外的编辑器功能:配置一个编辑器、打开编辑器、保存或取消行编辑,以及定义列编辑组件的工具方法。

为了支持框架的机制,例如数据容器、值来源等,列编辑器组件必须通过 DataGridEditorDataGridEditor#setColumnEditorComponent() 方法添加,而不能直接使用列 API Column#setEditorComponent()

参考示例:

@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 获取 DataGridEditor 实例。
2 JmixComboBox 组件实例用 UiComponents 工厂创建。
3 设置 StatusChangeHandler
4 setColumnEditorComponent() 方法返回的可视化组件将作为列编辑组件。

SupportsStatusChangeHandler

默认情况下,字段组件(例如,textFieldcomboBox)会在组件上方展示错误信息。但是在区域有限的单元格编辑器中,这种方式就不合适了。io.jmix.flowui.component.SupportsStatusChangeHandler 接口支持定义以不同的方式展示错误信息。实现了这个接口的组件支持错误信息代理。

行内编辑器默认使用 StatusChangeHandler,会将错误信息作为组件的 title 展示。

组件可以包含 header 和 footer 以显示补充信息。补充信息可以是一行或多行,通过下列方法添加:

方法

描述

appendHeaderRow()

在 header 块的底部添加一行。

prependHeaderRow()

在 header 块的顶部添加一行。

appendFooterRow()

在 footer 块的底部添加一行。

prependFooterRow()

在 footer 块的顶部添加一行。

下面的示例中,dataGrid 的 header 显示合并的单元格,而 footer 显示一些计算值:

data grid header footer
显示代码
<dataGrid id="dataGrid"
          width="100%"
          dataContainer="usersDc"
          themeNames="column-borders">
    <columns>
        <column property="firstName"/>
        <column property="lastName"/>
        <column property="active"/>
    </columns>
</dataGrid>
@ViewComponent
private DataGrid<User> dataGrid;
@ViewComponent
private CollectionContainer<User> usersDc;
@ViewComponent
private CollectionLoader<User> usersDl;
@Autowired
private DataManager dataManager;

@Subscribe
protected void onInit(final InitEvent event) {
    usersDl.load();
    initHeader();
    initFooter();
}

protected void initHeader() {
    HeaderRow headerRow = dataGrid.prependHeaderRow();
    HeaderRow.HeaderCell headerCell = headerRow.join(
            dataGrid.getColumnByKey("firstName"),
            dataGrid.getColumnByKey("lastName")); (1)
    headerCell.setText("Full Name");
}

protected void initFooter () {
    FooterRow footerRow = dataGrid.appendFooterRow();
    FooterRow.FooterCell activeCell = footerRow.getCell(dataGrid.getColumnByKey("active"));
    activeCell.setText(getActiveCount() + "/" + usersDc.getItems().size() );
}

protected int getActiveCount() {
    int activeCount = 0;
    Collection<User> items = dataGrid.getGenericDataView().getItems().toList();
    for (User user : items) {
        if (user.getActive()) {
            activeCount++;
        }
    }
    return activeCount;
}
1 header 中的单元格可以合并。以提供关于列的通用信息。
header 和 footer 都可以包含丰富的内容和组件。参考 在线示例

表头过滤

该功能目前是预览状态。其显示以及实现细节可能会在未来的版本中发生重大变化。

dataGrid 中的数据可以使用列标题中嵌入的 属性过滤器 进行过滤。

可以通过 XML 中的 filterable 属性定义哪些列可以进行过滤。可过滤的列表头中带有“漏斗”图标(funnel)。用户点击图标时,会显示一个包含属性过滤条件的对话框。如果设置了过滤条件,则该列中的图标将高亮显示。

若要确保过滤器图标始终正常显示,请使用 widthautoWidth 属性为列设置适当的宽度。最好不要让用户能调整列宽,否则用户有可能调小列宽导致过滤器图标不可见。

示例:

<dataGrid dataContainer="usersDc"
          width="100%">
    <columns>
        <column property="firstName" filterable="true"
                width="15em"/>
        <column property="lastName" filterable="true"
                autoWidth="true"/>
        <column property="username"/>
        <column property="active"/>
        <column property="joiningDate"/>
        <column property="onboardingStatus"/>
    </columns>
</dataGrid>

表头中的属性过滤器与独立属性过滤器或 genericFilter 通用过滤器 的工作方式相同 - 都是在 数据加载器 中添加查询条件。在标准流程中,过滤条件将转换为 JPQL 查询语句,并在数据库级别筛选数据。

可过滤的列可以与 propertyFiltergenericFilter 组件一起使用。所有过滤器的条件都由以 AND 逻辑运算进行组合。

目前,列过滤条件还没有绑定到页面的 URL 中。也就是说,如果用户使用了表头过滤器,然后导航到详情视图并返回,则表头过滤器将被清除。

操作

dataGrid 组件实现了 HasActions 接口,可以包含标准 列表操作 和自定义操作。操作通过相应的按钮或 右键菜单 调用。

data grid actions

如需在 Jmix Studio 中添加 action,可以在视图 XML 或 Jmix UI 结构中选择组件,然后在组件属性面板中点击 Add→Action 按钮。

显示代码
<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 定义一个 hbox 包含操作按钮。
2 定义 list_create 标准操作。
3 定义 getInfo 自定义操作。其 text 属性的值用于在右键菜单中显示该操作,并作为按钮的标题。

右键菜单

右键菜单提供了另一种访问 操作 的方式。每个操作显示为一个菜单项。

使用 contextMenu 元素可以优化菜单项列表,使用分隔符或层次结构进行组织。

data grid context menu
显示代码
<dataGrid width="100%" dataContainer="usersDc" id="menuDataGrid">
    <columns>
        <column property="username"/>
        <column property="firstName"/>
        <column property="lastName"/>
        <column property="active"/>
        <column property="onboardingStatus"/>
        <column property="joiningDate"/>
    </columns>
    <actions showInContextMenuEnabled="false"> (1)
        <action id="create" type="list_create"/>
        <action id="edit" type="list_edit"/>
        <action id="remove" type="list_remove"/>
        <action id="getInfo" text="View"/>
        <action id="sendMessage" text="Message"/>
    </actions>
    <contextMenu id="contextMenu">
        <item action="menuDataGrid.getInfo" icon="INFO_CIRCLE"/> (2)
        <separator/>
        <item text="Contact" icon="USER"> (3)
            <item action="menuDataGrid.sendMessage" icon="COMMENT"/>
            <item id="emailItem"/> (4)
        </item>
        <separator/>
        <item action="menuDataGrid.remove" icon="TRASH"/>
    </contextMenu>
</dataGrid>
1 隐藏菜单中所有的操作。或者使用 visible 属性隐藏特定操作。
2 为需要的操作显式添加菜单项。
3 菜单项互相包含以创建层级结构。
4 通过 dynamicContentHandler 动态添加的菜单项内容。
@ViewComponent
private GridMenuItem<Object> emailItem;

@Install(to = "contextMenu", subject = "dynamicContentHandler")
private boolean contextMenuDynamicContentHandler(final User user) {
    if (user == null) {
        return false;
    }
        emailItem.setText("Email: " + user.getEmail());
    return true;
}

渲染器

渲染器(Renderers)用来为数据网格中的数据实现自定义的展示方式。例如,可以用渲染器:

  • 格式化日期或数字。

  • 显示自定义的图标或图片。

  • 创建可交互的元素,比如按钮、链接等。

  • 根据单元格值的不同显示不同的内容。

渲染器可以通过三种方式定义:

  • 在 XML 中声明式定义

    XML 中可以使用一些预定义的列渲染器:

    • numberRenderer

    • localDateRenderer

    • localDateTimeRenderer

      这些渲染器需要传入一个 format 字符串。示例:

      <column property="joiningDate">
          <localDateRenderer format="MMM dd, yyyy"/>
      </column>

      如需通过 Jmix Studio 添加一个渲染器,在视图 XML 或 Jmix UI 的结构面板中选中 column 元素并点击属性面板中的 Add→<Some>Renderer

  • 使用 @Supply 注解定义

    渲染器可以在视图控制器中通过 @Supply 注解提供。使用 @Supply 注解的方法需要返回一个值,该值传递给“主体”中定义的一个方法。

    自定义的列渲染器可以用列的 renderer 处理方法定义,该方法可以在 Jmix Studio 中通过 column 元素属性面板的 Handlers 标签页创建。

    column 元素定义时,可以不使用 property 属性,即不直接绑定实体的某个属性。此时,column 元素必须带具有唯一值的 key 属性。

    可以参考 文本渲染器组件渲染器 示例。

  • 通过 addColumn() 和 addComponentColumn() 方法定义

    addColumn()addComponentColumn() 方法可以在数据网格中添加列。

    可以配置新添加的列使用渲染器展示数据。

    下面的示例中,我们添加一列用于展示用户的图片:

    @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 添加一列,显示 image 组件。
    2 Image 组件的实例使用 UiComponents 工厂创建。
    3 image 从给定的 StreamResource 获取内容,存储在 User 实体的 picture 属性中。
    4 addComponentColumn() 方法返回的可视化组件展示在列单元格中。

本地日期渲染器

LocalDateRenderer 用于以 LocalDate 值的形式展示日期。

在数据网格的 column 元素中,支持 localDateRenderer 子元素,该元素可以包含一个可选的 nullRepresentation 属性和一个必需的 format 字符串属性。

<column property="joiningDate">
    <localDateRenderer format="MMM dd, yyyy"/>
</column>

nullRepresentation 属性用于展示 null 值的文本。

下面的示例中,在 addColumn() 方法使用了 LocalDateRenderer

@ViewComponent
private DataGrid<User> usersDtGr;

@Subscribe
public void onInit(InitEvent event) {
    usersDtGr.addColumn(new LocalDateRenderer<>(
                    User::getJoiningDate,
                    () -> DateTimeFormatter.ofLocalizedDate(
                            FormatStyle.MEDIUM)))
            .setHeader("Joining date");
}

本地日期时间渲染器

LocalDateTimeRenderer 用于以 LocalDateTime 值的形式展示日期。

在数据网格的 column 元素中,支持 localDateTimeRenderer 子元素,该元素可以包含一个可选的 nullRepresentation 属性和一个必需的 format 字符串属性。

<column property="passwordExpiration">
    <localDateTimeRenderer format="dd/MM/YYYY HH:mm:ss"/>
</column>

nullRepresentation 属性用于展示 null 值的文本。

数字渲染器

NumberRenderer 用于在单元格中以指定的格式显示数字。

在数据网格的 column 元素中,支持 numberRenderer 子元素,该元素可以包含一个可选的 nullRepresentation 属性和一个必需的 formatnumberFormat 字符串属性。

<column property="factor">
    <numberRenderer numberFormat="#,#00.0000"/>
</column>

nullRepresentation 属性用于展示 null 值的文本。

numberFormat 属性需按照 java.text.DecimalFormat 类规定的格式和语法进行配置。

numberRenderer 需且仅需定义一个格式,formatnumberFormat。如果未定义或两者都定义会抛出 GuiDevelopmenException 异常。

文本渲染器

TextRenderer 渲染器用于展示文本。

下面的示例中,列展示了一个自定义的文本:

<column key="status" header="Status"/>
@Supply(to = "userStepsDataGrid.status", subject = "renderer")
private Renderer<UserStep> userStepsDataGridStatusRenderer() {
    return new TextRenderer<>(userStep ->
            isOverdue(userStep) ? "Overdue!" : "");
}

组件渲染器

下面的示例显示如何在列中使用一个自定义的渲染器显示一个复选框:

<column key="completed" width="4em" flexGrow="0"/>
@Supply(to = "userStepsDataGrid.completed", subject = "renderer")
private Renderer<UserStep> userStepsDataGridCompletedRenderer() {
    return new ComponentRenderer<>(userStep -> {
        JmixCheckbox checkbox = uiComponents.create(JmixCheckbox.class);
        checkbox.setValue(userStep.getCompletedDate() != null);
        checkbox.addValueChangeListener(e -> {
            // ...
        });
        return checkbox;
    });
}

条目详情

组件中的行可以展开,以显示每行的附加信息。通过 setItemDetailsRenderer() 方法可以实现该功能。方法使用一个 ComponentRenderer 作为参数,提供内容的渲染方式。

data grid items details

detailsVisibleOnClick 属性可以设置当点击特定行时,是否显示详细信息。如果需要通过其他事件触发详情展示,可以设置该属性为 false

排序

任何列都可用于对数据进行排序。单击列标题可激活表格中的特殊控件,该控件显示当前正在排序的列以及排序的顺序(升序或降序)。随后每次单击同一标题都可以切换排序的顺序。

多列排序

也可以同时按多列进行排序。按多列排序时,第一个选定的列确定主要排序条件,第二列设置次要排序条件,依此类推。可以使用 multiSortmultiSortOnShiftClickOnlymultiSortPriority 属性配置多列排序。

示例:

<dataGrid width="100%"
          dataContainer="usersDc"
          multiSort="true"
          multiSortOnShiftClickOnly="true"
          multiSortPriority="APPEND">

聚合

dataGrid 可以对行内值进行聚合。当启用聚合时,会显示一个附加行,包含聚合值。示例:

<dataGrid width="100%"
          dataContainer="stepsDc"
          aggregatable="true"
          aggregationPosition="TOP"> (1)
    <columns>
        <column property="name"/>
        <column property="duration">
            <aggregation type="AVG"
                         cellTitle="msg://aggregation.cellTitle"/> (2)
        </column>
        <column property="sortValue"/>
        <column property="factor">
            <aggregation type="AVG">
                <formatter>
                    <number format="#,##0.00"/> (3)
                </formatter>
            </aggregation>
        </column>
    </columns>
</dataGrid>
1 设置 aggregatable 属性为 true
2 为需要进行聚合运算的列设置 aggregation 元素。还可以使用 cellTitle 属性配置用户鼠标悬浮在聚合值上时显示的提示信息。
3 指定 formatter 可以为聚合值设置不同于标准数据类型格式的其他展示格式。

aggregation 元素还可以通过 strategyClass 属性设置一个用于自定义聚合计算的类:

<dataGrid width="100%"
          dataContainer="usersDc"
          aggregatable="true"
          aggregationPosition="TOP">
    <columns>
        <column property="firstName"/>
        <column property="lastName"/>
        <column property="onboardingStatus">
            <aggregation
                    strategyClass="com.company.onboarding.view.component.datagrid.DataGridUserStatusAggregation"/>
        </column>
    </columns>
</dataGrid>

该类需要实现 AggregationStrategy 接口。示例:

public class DataGridUserStatusAggregation implements AggregationStrategy<OnboardingStatus, String> {

    @Autowired
    public Messages messages;

    @Override
    public String aggregate(Collection<OnboardingStatus> propertyValues) {
        OnboardingStatus mostFrequent = null;
        long max = 0;

        if (CollectionUtils.isNotEmpty(propertyValues)) {
            for (OnboardingStatus status : OnboardingStatus.values()) {
                long current = propertyValues.stream()
                        .filter(status :: equals)
                        .count();

                if (current > max) {
                    mostFrequent = status;
                    max = current;
                }
            }
        }

        if (mostFrequent != null) {
            String key = OnboardingStatus.class.getSimpleName() + "." + mostFrequent.name();
            return String.format("%s: %d/%d", messages.getMessage(OnboardingStatus.class, key), max, propertyValues.size());
        }

        return null;
    }

    @Override
    public Class<String> getResultClass() {
        return String.class;
    }
}

XML 属性

在 Jmix 中,所有组件都有一些作用一致的 通用属性。 下面是 dataGrid 的特殊属性:

名称

描述

默认值

allRowsVisible

如果设置为 true,表格会一次显示所有的行,不带滚动条。也就是说,此时不会仅显示那些可见行,等用户滚动到底部才加载更多数据,而是会直接在 DOM 中同时渲染所有的数据。

如果有大量数据,会有性能问题,此时不推荐使用该功能。

false

aggregatable

如果设置为 true,则启用表格的聚合功能。参阅 聚合

false

aggregationPosition

如果组件中的数据 可以聚合,则用该属性配置聚合行的显示位置。支持 TOPBOTTOM。参阅 聚合

BOTTOM

columnReorderingAllowed

如果设置为 true,则用户可以修改表格列的顺序。

false

detailsVisibleOnClick

如果设置为 true,当用户点击特定行时,显示 条目详情

true

dropMode

设置行的拖放模式。支持 BETWEENON_TOPON_TOP_OR_BETWEENON_GRID。该功能可用于行的顺序调整或在不同表格之间拖放数据。

-

editorBuffered

如果设置为 true,则启用缓存模式的 行内编辑,只有当用户点击保存按钮时才会提交改动。该模式下用户也可以取消修改。在非缓存模式时,改动会自动提交。

false

multiSort

如果设置为 true,则启用多列排序。

false

multiSortOnShiftClickOnly

如果设置为 true,仅当按住 Shift 键并单击列标题时,才会激活多列排序。

false

multiSortPriority

设置点击的列添加到排序列中的位置。支持 PREPENDAPPEND

PREPEND

nestedNullBehavior

设置解析可能包含 null 值的内部属性时的行为。支持 THROWALLOW_NULLS

THROW

pageSize

设置每页展示的行数,这个数值也是每次从数据提供器中获取的数量。

50

rowDraggable

如果设置为 true,启用表格的行拖放功能。

false

selectionMode

设置选择模式。支持 SINGLEMULTI

SINGLE

事件和处理器

在 Jmix 中,所有组件都有一些 通用事件和处理器,可以按相同的方法设置。 下面是 dataGrid 的特殊事件和处理器:

在 Jmix Studio 生成处理器桩代码时,可以使用 Jmix UI 组件面板的 Handlers 标签页或者视图类顶部面板的 Generate Handler 添加,也可以通过 CodeGenerate 菜单(Alt+Insert / Cmd+N)生成。

名称

描述

CellFocusEvent

com.vaadin.flow.component.grid.CellFocusEvent 当数据网格的某个单元格获得焦点时发送。对应 grid-cell-focus DOM 事件。

ColumnReorderEvent

com.vaadin.flow.component.grid.ColumnReorderEvent 当数据网格的列重排时发送。对应 column-reorder-all-columns DOM 事件。

ColumnResizeEvent

com.vaadin.flow.component.grid.ColumnResizeEvent 当用户改变数据网格列大小时发送。对应 column-drag-resize DOM 事件。

GridDragEndEvent

com.vaadin.flow.component.grid.dnd.GridDragEndEvent 当数据网格的行拖放结束时发送。对应 grid-dragend DOM 事件。

GridDragStartEvent

com.vaadin.flow.component.grid.dnd.GridDragStartEvent 当数据网格的行拖放开始时发送。对应 grid-dragstart DOM 事件。

GridDropEvent

com.vaadin.flow.component.grid.dnd.GridDropEvent 当拖放至数据网格或数据行时发送。对应 grid-drop DOM 事件。

ItemClickEvent

com.vaadin.flow.component.grid.ItemClickEvent 当点击数据网格条目时发送。对应 item-click DOM 事件。

ItemDoubleClickEvent

com.vaadin.flow.component.grid.ItemDoubleClickEvent 当双击数据网格条目时发送。对应 item-double-click DOM 事件。

SortEvent

com.vaadin.flow.data.event.SortEvent 描述 DataProvider 中排序变化的事件。由 SortNotifiers 触发。

classNameGenerator

为数据网格中所有的单元格生成 CSS 类名。

dataGenerator

为数据网格添加数据生成器。如果已经添加,则不做操作。参考 com.vaadin.flow.data.provider.HasDataGenerators 接口。

dragFilter

用于控制特定行是否可拖放,而不是通过 rowDraggable 设置所有行的拖放。

dropFilter

用于设置哪些行可以作为拖放的目的地。

enterPressHandler

用户按下回车键的处理器。

tooltipGenerator

按照给定条件为列单元格生成提示窗。参考 在线示例

XML 内部元素

dataGrid 的 XML 内部元素提供很多选项来控制列的外观、行为和功能,既可以集中控制列,也可以单独控制列的功能。

如需为选择的组件添加内部元素,可以使用 Jmix UI 组件属性面板中的 Add 按钮添加。

columns

columns 元素可以设置一组需要展示的属性,并设置所有列的行为。

XML 元素

columns

属性

exclude - includeAll - resizable - sortable

XML 内部元素

column - EditorActionsColumn

属性

名称

描述

默认值

exclude

排除特定的属性卡不予展示。多个属性需要使用逗号分隔。示例:exclude = "id, version, sortValue"

-

includeAll

如果为 true,则包含数据容器 fetch plan 中的所有属性。

-

resizable

如果设置为 true,所有列都支持用户改变宽度。

false

sortable

如果设置为 true,所有列都支持排序。

true

column

column 元素定义一个单独的列。为单独列设置的属性会覆盖为所有列设置的属性。

XML 元素

column

属性

autowidth - editable - filterable - flexGrow - footer - frozen - header - key - property - resizable - sortable - textAlign - visible - width

事件和处理器

AttachEvent - DataGridColumnVisibilityChangedEvent - DetachEvent - classNameGenerator - partNameGenerator - renderer - tooltipGenerator

XML 内部元素

Aggregation - LocalDateRenderer - LocalDateTimeRenderer - NumberRenderer

属性

名称

描述

默认值

autoWidth

如果设置为 true,列宽根据内容自动调整。

false

editable

如果设置为 true,列可编辑。参阅 行内编辑

false

filterable

如果设置为 true,启用该列的过滤。参阅 表头过滤

false

flexGrow

设置列的 flex grow 比例。当设置为 0 时,列宽固定。

0

footer

为列设置一个 footer 文本。该属性可以是文本本身或者 消息包 中的一个键值。如果是消息包键值,则必须以 msg:// 开头。

-

frozen

如果设置为 true,则锁住该列。用户在水平滚动表格时会一直显示锁住的列。建议从左至右依次锁定列。

false

header

为列设置一个 header 文本。该属性可以是文本本身或者 消息包 中的一个键值。如果是消息包键值,则必须以 msg:// 开头。

-

key

设置用户定义的列映射 id。这个键值可以用来通过 getColumnByKey(String) 方法获取该列。

键值必须在同一个数据网格中唯一,设定后不能更改。

-

property

指定列中需要显示的实体属性。可以是根实体的属性 property = "user",也可以是子实体的属性 property = "user.department.name"(并通过 “.” 变量对象图)。

-

resizable

如果设置为 true,用户可以手动调整列宽。

false

sortable

如果设置为 true,列可排序。

false

textAlign

设置文本的对其方式,支持 STARTCENTEREND。参考文本对齐。

START

visible

如果设置为 true,则列可见。

true

width

用 CSS 字符串设置列宽。

-

事件和处理器

名称

描述

DataGridColumnVisibilityChangedEvent

通过 gridColumnVisibility 列可见性 组件修改列可见性时发送。

classNameGenerator

按照给定条件为列生成 CSS 类名。此功能可以根据展示的数据修改单元格的外观。

partNameGenerator

按照给定条件为列生成 CSS 类的 part。此功能可以根据展示的数据修改单元格的外观。参考 在线示例

renderer

使用文本或组件选人列内容。参阅 文本渲染器组件渲染器

tooltipGenerator

按照给定条件为列生成提示窗。参考 在线示例

contextMenu

contextMenu 元素可以使用与其默认排列方式不同的方式组织右键菜单的条目。请参阅 示例

XML 元素

contextMenu

属性

id - classNames - css - enabled - visible

事件和处理器

AttachEvent - DetachEvent - GridContextMenuOpenedEvent - openedChangeEvent - dynamicContentHandler

XML 内部元素

item - separator

事件和处理器

名称

描述

GridContextMenuOpenedEvent

当右键菜单的打开状态变化时触发。可以返回目标菜单项本身或 id,能根据点击事件调整菜单项的展示。

openedChangeEvent

当右键菜单的打开状态变化时触发。

dynamicContentHandler

在菜单打开时处理菜单的动态更新,例如添加菜单项或其内容。请参阅 示例

参考