Table 表格

Table - 表格 组件以表格的方式展示信息、对数据进行排序、管理表格列和表头,并对选中的行执行操作。

组件的 XML 名称:table。

基本用法

典型的表格如下所示:

table anatomy
  1. 表头

  2. 数据行

  3. 列控制按钮

  4. 分页器

  5. 排序按钮

  6. 按钮面板

在界面 XML 描述中定义表格组件的示例:

<data>
    <collection id="customersDc" class="ui.ex1.entity.Customer">
        <fetchPlan extends="_base"/>
        <loader id="customersDl">
            <query>
                <![CDATA[select e from uiex1_Customer e]]>
            </query>
        </loader>
    </collection>
</data>
<layout>
    <table id="customersTable"
           width="100%"
           dataContainer="customersDc">
        <actions>
            <action id="create" type="create"/>
            <action id="edit" type="edit"/>
            <action id="remove" type="remove"/>
            <action id="sendByEmail" type="sendByEmail">
                <properties>
                    <property name="recipientAddress" value="peter@example.com"/>
                </properties>
            </action>
        </actions>
        <columns>
            <column id="level"/>
            <column id="age"/>
            <column id="hobby"/>
            <column id="firstName"/>
            <column id="lastName"/>
            <column id="rewardPoints"/>
        </columns>
        <simplePagination/>
        <buttonsPanel id="buttonsPanel" alwaysVisible="true">
            <button id="createBtn" action="customersTable.create"/>
            <button id="editBtn" action="customersTable.edit"/>
            <button id="removeBtn" action="customersTable.remove"/>
            <button id="sendBtn" action="customersTable.sendByEmail"/>
        </buttonsPanel>
    </table>
</layout>

在上面的示例中,为 Customer 实体使用了 集合数据容器。Table 组件通过 dataContainer 属性与数据容器绑定,columns 元素定义那些实体属性要显示在数据网格的列中。

数据绑定

声明式绑定

通常,使用 dataContainer 属性在界面 XML 描述中将数据与 table 绑定。此时需要使用一个 集合数据容器。

使用键值对容器

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

<data>
    <keyValueCollection id="salesDc">
        <loader id="salesLoader">
            <query>
                <![CDATA[select o.customer, o.customer.firstName,
                sum(o.amount) from uiex1_Order o group by o.customer]]>
            </query>
        </loader>
        <properties>
            <property class="ui.ex1.entity.Customer" name="customerEntity"/>
            <property datatype="string" name="customerName"/>
            <property datatype="decimal" name="sum"/>
        </properties>
    </keyValueCollection>
</data>
<layout>
    <table id="keyValueTable" width="100%" dataContainer="salesDc">
        <columns>
            <column id="customerName" caption="Customer"/>
            <column id="sum" caption="Summary amount" align="RIGHT"/>
        </columns>
    </table>
</layout>

编程式绑定

如需以编程的方式在界面控制器定义数据容器,则可以在 XML 中设置 metaClass 属性而非 dataContainer。

<table id="customersTable1" width="100%" metaClass="uiex1_Customer">
    <columns>
        <column id="firstName"/>
        <column id="lastName"/>
    </columns>
</table>

界面控制器中,使用 ContainerTableItems 类将表格和数据容器绑定:

customersTable1.setItems(new ContainerTableItems<>(customersDc));

columns 元素

表格的列集合定义在 columns 元素中。如果未指定,则通过 dataContainer 定义的 fetch plan 自动确定。

columns 元素有如下属性:

  • includeAll 加载 dataContainer 中定义的 fetchPlan 的所有属性。

    在下面的例子中,我们显示了 customersDc 中使用 fetch plan 的所有属性:

    <table id="customersTableIncludeAll"
           width="100%"
           dataContainer="customersDc">
        <columns includeAll="true"/>
    </table>

    如果实体的 fetch plan 包含引用属性,该属性会按照其 实例名 进行展示。如果需要展示一个特定的级联属性,则需要在 fetch plan 和 column 元素中定义:

    <data>
        <collection id="customersDc1" class="ui.ex1.entity.Customer">
            <fetchPlan extends="_base">
                <property name="city" fetchPlan="_base">
                    <property name="country" fetchPlan="_base"/>
                </property>
            </fetchPlan>
            <loader id="customersDl1">
                <query>
                    <![CDATA[select e from uiex1_Customer e]]>
                </query>
            </loader>
        </collection>
    </data>
    <layout>
        <table id="tableIncludeAllReference"
               width="100%"
               dataContainer="customersDc1">
            <columns includeAll="true">
                <column id="city.country.name"/>
            </columns>
        </table>
    </layout>
  • exclude exclude 英文逗号分隔的属性列表,这些属性不会被加载到表格。

    在下面的例子中,我们会显示除了 id、maritalStatus 和 email 之外的所有属性:

    <table id="tableExclude"
           width="100%"
           dataContainer="customersDc1">
        <columns includeAll="true"
                 exclude="id,maritalStatus,email"/>
    </table>

column 元素

每一列是在内部的 column 元素中描述。

id 是一个必需属性,指定展示在列中实体属性的名称。可以是数据容器中实体的一个属性或者一个关联实体(用 . 访问对象关系图)。示例:

<columns>
    <column id="firstName"/>
    <column id="lastName"/>
    <column id="city.name"/>
    <column id="city.country.name"/>
</columns>

如需在 Jmix Studio 中添加 column,可以在界面 XML 或者 Component Hierarchy 面板中选择 columns 元素,然后点击 Component Inspector 面板的Add→Column 按钮。

列对齐

支持三种类型的列对齐方式:LEFT(默认)、CENTER、RIGHT。

通常数字采用右对齐,而其他内容采用左对齐。示例:

<table id="keyValueTable" width="100%" dataContainer="salesDc">
    <columns>
        <column id="customerName" caption="Customer"/>
        <column id="sum" caption="Summary amount" align="RIGHT"/>
    </columns>
</table>
table column align

列标题

caption - 可选属性,定义列标题。如果未设置,会使用实体属性的 本地化名称。

captionAsHtml - 可选属性,定义是否可以在列标题中使用 HTML 标签。默认为 false。

<column id="firstName"
        captionAsHtml="true"
        caption="msg://firstName"/> (1)
<column id="lastName"/> (2)
1 列标题含有 HTML 标签:
ui.ex1.screen.component.table/firstName=<em>First Name</em>
2 默认标题列
table captions

列可见性

collapsed - 可选属性,设置为 true 时自动隐藏该列。collapsed 属性默认值为 false。用户可以通过表格右上角的 table column control button 按钮提供的菜单控制列的可见性,此时需要设置 columnControlVisible 为 true。

visible 属性设置列的可见性。可选值:true、false。默认所有列都可见。

下面示例中,我们看看 collapsed 和 visible 属性的不同之处:

<columns>
    <column id="firstName"
            collapsed="true"/>
    <column id="lastName"
            visible="false"/>
    <column id="city"/>
</columns>
table columns visibility

可以看到,firstName 列默认是折叠不显示的,但是用户可以通过 table column control button 按钮的下拉菜单显示它。

同时,lastName 是无法通过用户操作看见的。

列宽度

width - 可选属性,定义列宽。只支持以像素为单位的数值类型。

<columns>
    <column id="firstName" width="100"/>
    <column id="lastName" width="150"/>
    <column id="city" width="100"/>
</columns>
table column width

expandRatio - 可选属性,设置列宽占比。比值必须大于等于 0。如果至少有一列设置了其他值,则忽略所有的隐式值,并且只使用设置的值。如果同时设置了 width 和 expandRatio 属性,会导致应用程序错误。

<columns>
    <column id="firstName" expandRatio="1"/>
    <column id="lastName" expandRatio="1.5"/>
    <column id="city" expandRatio="1"/>
</columns>
table column expand ratio

用户可以调整列宽:

table columns resize

只有当整个表的 enable 属性设置为 false 时,列才维持固定宽度。

列重排

Table 提供拖拽功能,用户可以改变表格内列的展示顺序。

table columns reordering

列重排的功能是默认开启的。如需禁用,可设置 reorderingAllowed 属性为 false。

<column id="firstName"
        link="true"
        linkScreenOpenMode="DIALOG"/>
<column id="lastName"/>
<column id="city"/>
table columns link

文本最大长度

maxTextLength - 可选属性,允许限制单元格中的字符数。多余字符用省略号代替。用户可以点击可见部分来查看完整的文本。

如果实际值和最大允许字符数之间的差异不超过 10 个字符,则多余字符仍然显示。

下面例子中,有些单元格的值长度大于 maxTextLength+10,则省略。

<columns>
    <column id="firstName"/>
    <column id="lastName"/>
    <column id="email" maxTextLength="15"/>
    <column id="city"/>
</columns>
table max text length

文本格式化

column 元素可以包含一个内部的 formatter 元素,支持以不同于 Datatype 标准的格式显示属性值:

<table id="tableColumnFormatter"
       width="100%"
       dataContainer="ordersDc">
    <columns>
        <column id="customer"/>
        <column id="amount"/>
        <column id="deliveryTime">
            <formatter>
                <date format="h:mm a"/>
            </formatter>
        </column>
    </columns>
</table>

标题属性

captionProperty 属性指定一个要显示在列中的实体属性名称,而不是显示 id 指定的实体属性值。例如,如果有一个包含 name 和 id 属性的实体 City,则可以定义以下列:

<column id="city"
        caption="City ID"
        captionProperty="id"/>

此时,列中将会显示 City 实体的 id 属性,但是列的排序是根据 City 实体的 name 属性。

table captions

多行单元格

将 multiLineCells 设置为 true 可以让包含多行文本的单元格显示多行。在这种模式下,浏览器会一次加载表格中当前页的所有行,而不是延迟加载表格的可见部分。这样会使得数据带滚动条并可能影响性能。默认值为 false。

table multi line cell

选择

Table 组件支持对数据行进行单选和多选。

单选模式

在单选模式中,用户一次只能选择单一的数据行。这是表格默认的选择模式。

多选模式

multiselect 属性可以为表格行设置多选模式。如果 multiselect 为 true,用户可以按住 Ctrl 或 Shift 键在表格中选择多行。默认情况下关闭多选模式。

显示选择行

如果 showSelection 属性设置为 false,则不高亮显示当前行。

文本选取

textSelectionEnabled 属性定义是否可以在单元格中选取文本。默认值 false。

空状态

在数据容器没有数据或者没有设置数据容器时,支持为 Table 设置展示空状态消息或链接。

空状态消息通过 emptyStateMessage 属性定义。可以用于显示无数据的原因。

示例:

<table id="tablePlaceholder"
       width="100%"
       height="200"
       metaClass="uiex1_Customer"
       emptyStateMessage="No customers added."
       emptyStateLinkMessage="Add customer">
    <columns>
        <column id="firstName"/>
        <column id="lastName"/>
    </columns>
</table>
table placeholder

生成 emptyStateLinkClickHandler 处理空状态链接的点击:

@Install(to = "tablePlaceholder", subject = "emptyStateLinkClickHandler")
private void tablePlaceholderEmptyStateLinkClickHandler(
        Table.EmptyStateClickEvent<Customer> emptyStateClickEvent) {
    screenBuilders.editor(emptyStateClickEvent.getSource())
            .newEntity()
            .show();
}

如需以编程的方式注册点击处理器,使用组件的 setEmptyStateLinkClickHandler() 方法。

emptyStateMessage 和 emptyStateLinkMessage 属性都可以从 消息包 中加载本地化消息。

表头可见性

columnHeaderVisible 设置表格的表头是否展示。默认展示。

列可见控制

用户可以用表格 header 右侧的 table column control button 列控制按钮选择显示哪些列。

当前展示列在下拉列表中是勾选状态。其他的菜单项:

  • Select all - 展示所有列。

  • Deselect all - 隐藏除了第一列之外所有能隐藏的列。第一列必须显示,以保证表格功能正常。

table column control using

如果 columnControlVisible 属性设置为 false,则用户不能隐藏列。

聚合

Table 支持对行内值进行聚合运算。

支持下列运算符:

  • SUM - 求和

  • AVG - 求平均值

  • COUNT - 计数

  • MIN - 最小值

  • MAX - 最大值

如需启用对表格的行进行聚合运算,按照下列配置:

  1. 设置 aggregatable 属性值为 true。

  2. 为表格的聚合列设置 aggregation 元素。

  3. 设置 aggregation 元素的 type 属性,表示聚合的函数。

如需在 Jmix Studio 中定义 aggregation,可以在界面 XML 或者 Component Hierarchy 面板中选择聚合单元格的列,然后点击 Component Inspector 面板的 Add→Aggregation 按钮。

聚合值展示在附加行中。

aggregationStyle 属性可以设置聚合值行的位置:TOP 或 BOTTOM。默认为 TOP。

默认情况下,聚合列只支持数字类型,比如 Integer、Double、Long 和 BigDecimal。

带聚合列的 Table XML 描述示例:

<table id="tableAggregation"
       width="100%"
       aggregatable="true"
       dataContainer="customersDc1">
    <columns>
        <column id="firstName"/>
        <column id="lastName"/>
        <column id="rewardPoints"/>
        <column id="age">
            <aggregation type="AVG"/>
        </column>
    </columns>
</table>
table aggregation

valueDescription 属性定义一个提示,当用户的光标悬停在聚合值上时通过弹出框展示这个提示。对于上面列出的运算(SUM、AVG、COUNT、MIN、MAX),提示弹窗已经默认开启。

aggregation 元素支持 editable 属性。设置该属性为 true,且配合使用 AggregationDistributionProvider 可以支持开发者实现在各行之间分配数据。

可以指定不同于 Datatype 标准格式的 formatter 显示聚合值:

<column id="amount">
    <aggregation type="SUM">
        <formatter>
            <number format="#,##0.00"/>
        </formatter>
    </aggregation>
</column>

aggregation 元素还可以包含 strategyClass 属性,指定一个实现 AggregationStrategy 接口的类。

public class TableCustomerHobbyAggregation implements AggregationStrategy<Hobby, String> {
    @Override
    public String aggregate(Collection<Hobby> propertyValues) {
        Hobby mostFrequent = null;
        long max = 0;
        if (CollectionUtils.isNotEmpty(propertyValues)) {
            for (Hobby hobby : Hobby.values()) {
                long current = propertyValues.stream()
                        .filter(customerHobby -> customerHobby.equals(hobby))
                        .count();

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

        if (mostFrequent != null) {
            return String.format("%s: %d/%d", mostFrequent.name(), max, propertyValues.size());
        }

        return null;
    }

    @Override
    public Class<String> getResultClass() {
        return String.class;
    }
}
<table id="tableAggregationStrategy"
       width="100%"
       aggregatable="true"
       dataContainer="customersDc">
    <columns>
        <column id="firstName"/>
        <column id="lastName"/>
        <column id="hobby">
            <aggregation
                    strategyClass="ui.ex1.screen.component.table.TableCustomerHobbyAggregation"/>
        </column>
    </columns>
</table>

排序

Table 支持对列数据进行排序。排序功能默认开启。

sortable 属性可以启用表格的排序功能。默认为 true。开启后,点击列名会在列名右边显示 table sortable down/table sortable up 图标。

使用特定 列 的 sortable 属性可以禁用该列的排序功能。

下面的例子中,我们禁用了 lastName 列的排序:

<columns>
    <column id="firstName"/>
    <column id="lastName" sortable="false"/>
    <column id="city"/>
</columns>

column 元素的 sort 属性可以设置该列的初始排序。值选项:

  • ASCENDING - 顺序(0 → 9 → A → Z)。

  • DESCENDING - 倒序(Z → A → 9 → 0)。

示例:

<columns>
    <column id="firstName" sort="DESCENDING"/>
    <column id="lastName"/>
    <column id="city"/>
</columns>

Table 一次只能按照一列进行排序。如果有多列设置了 sort 属性或者同时设置了 sort 和 sortable="false",界面会报错。

分页

table 可以使用 SimplePagination 简单分页器 组件来提供分页功能:

<table id="tablePaging"
       width="100%"
       dataContainer="customersDc">
    <columns>
        <column id="firstName"/>
        <column id="lastName"/>
        <column id="hobby"/>
        <column id="age"/>
    </columns>
    <simplePagination
            itemsPerPageVisible="true"
            itemsPerPageOptions="2, 4, 6"/>
</table>
table pagination

或者,可以使用独立的 Pagination 分页 组件。

Table 操作

Table 组件实现了 ActionsHolder 接口,可以包含自定义操作和 标准列表操作。

表格的操作定义在内部的 actions 元素中。

如需在 Jmix Studio 中添加 action,可以在界面 XML 或者 Component Hierarchy 面板中选择组件,然后点击 Component Inspector 面板的 Add→Action 按钮。

如果操作有标题,则会显示在表格的 右键菜单 中。此外,表格的操作可以分配给界面中任意位置的按钮。

可以用 ButtonsPanel 容器在表格上方显示操作按钮。

<table id="tableWithActions"
       width="100%"
       dataContainer="customersDc">
    <actions>
        <action id="create" type="create"/> (1)
        <action id="edit" type="edit"/>
        <action id="remove" type="remove"/>
        <action id="about" caption="Get info"/> (2)
    </actions>
    <columns>
        <column id="age"/>
        <column id="firstName"/>
        <column id="lastName"/>
    </columns>
    <buttonsPanel id="buttonsActionsPanel" alwaysVisible="true"> (3)
        <button id="create" action="tableWithActions.create"/>
        <button id="edit" action="tableWithActions.edit"/>
        <button id="remove" action="tableWithActions.remove"/>
        <button id="about" action="tableWithActions.about"/>
    </buttonsPanel>
</table>
1 定义 create 标准操作。
2 定义 about 自定义操作。
3 在表格内定义 ButtonsPanel 容器。
table actions

列生成

通过 columnGenerator 处理器可以提供自定义的列数据展示。

在渲染表格时,事件处理器由框架对每个单元格进行调用。处理器接收对应渲染行的实体实例作为参数,返回在单元格中需要展示的可视化组件。

可以用 Studio 为表格列创建 columnGenerator 处理器(参阅 处理器),并实现如下:

@Install(to = "tableGeneratedColumn.hasEmail", subject = "columnGenerator")
private Component tableGeneratedColumnIsEmailColumnGenerator(Customer customer) {
    CheckBox hasEmail = uiComponents.create(CheckBox.class);
    hasEmail.setValue(customer.getEmail() != null);
    return hasEmail;
}

如只需展示动态文本,可以用特殊的 Table.PlainTextCell 类而不是 Label 组件。这样渲染更快,表格性能也更好。

@Install(to = "tableGeneratedColumn.fullName", subject = "columnGenerator")
private Component tableGeneratedColumnFullNameColumnGenerator(Customer customer) {
    return new Table.PlainTextCell(customer.getFirstName() + " " + customer.getLastName());
}
<table id="tableGeneratedColumn"
       width="100%"
       dataContainer="customersDc">
    <columns>
        <column id="age"/>
        <column id="firstName"/>
        <column id="lastName"/>
        <column id="fullName" caption="Full name"/>
        <column id="email"/>
        <column id="hasEmail" caption="Has email"/>
    </columns>
</table>

fullName 和 isEmail 是生成列。

table generated columns

当列的 id 指定关联实体的属性时(即,包含 “.”),columnGeneration 处理器需要按照下面示例中的方法定义。

  • 关联实体属性列:

    <column id="city.country.name"/>
  • 对应的 columnGenerator 处理器:

    @Install(to = "countryTable.[city.country.name]", subject = "columnGenerator")
    private Component countryTableCityCountryNameColumnGenerator(Customer customer) {
        return new Table.PlainTextCell(customer.getCity().getCountry().getName());
    }

如需以编程的方式注册列生成处理器,使用 Table 组件的 addGeneratedColumn() 方法。该方法需要两个参数:列的标识符和 Table.ColumnGenerator 接口的实现。如果标识符可以匹配 XML 描述中为表格列设置的标识符,则用新列代替 XML 中定义的列。如果标识符与任何列都不匹配,则会在右侧添加新列。

Table.ColumnGenerator 接口的 generateCell() 方法与上面介绍的 columnGenerator 处理器等效:接收对应渲染行的实体实例作为参数,返回在单元格中需要展示的可视化组件。

列值导出

使用 表格导出 扩展组件可以将 Table 组件的内容导出成支持的文件类型。

安装完组件后,可以为表格定义 excelExport 或 jsonExport 操作,也可使用 表格导出器。

如过使用了自定义生成列,则默认不会导出这些列的内容。参考 导出带生成列的表格 中的示例。

下面的例子中,在使用 excelExport 操作导出时,为数据的某一列设置了自定义的输出。

界面描述:

<table id="printableTable"
       width="100%"
       dataContainer="customersDc1">
    <actions>
        <action id="excelExport" type="excelExport"/>
    </actions>
</table>

界面控制器:

@Named("printableTable.excelExport")
protected ExcelExportAction printableTableExcelExport;

@Subscribe
public void onInit(InitEvent event) {
    printableTableExcelExport.addColumnValueProvider("firstName", context -> { (1)
        Customer customer = context.getEntity();
        return "Name: " + customer.getFirstName();
    });
}
1 该方法一个参数是列标识符,第二个是从列中获取展示值的函数。

表格编辑

表格可以配置支持行内编辑。

用 editable 属性可以将表格转换至编辑模式。

在这种模式下,具有 editable = true 属性的列显示用于编辑相应实体属性的组件。运行时无法修改此属性设置。

根据相应实体属性的类型自动选择每个可编辑列的组件类型。例如,对于字符串和数字类型的属性,使用 TextField,日期时间 - DateField,枚举 - ComboBox,实体引用 - EntityPicker。

对于 Date 类型的可编辑列,还可以定义 dateFormat 或 resolution 属性,与 DateField 中相同属性类似。

可以为显示关联实体的可编辑列定义 optionsContainer 和 captionProperty 属性。如果设置了 optionsContainer 属性,应用程序将使用 ComboBox 而不是 EntityPicker。

右键菜单

在表格中点击右键可以激活右键菜单。

contextMenuEnabled 属性可以开启右键菜单。默认值为 true。右键菜单展示 表格操作(如果有的话)。

table context menu

样式

可以在界面 XML 或者控制器中使用 stylename 属性为 Table 组件设置预定义样式:

<table id="tableBorderless"
       caption="Table with borderless style"
       width="100%"
       stylename="borderless"
       dataContainer="customersDc1">
tableBorderless.setStyleName(ThemeClassNames.TABLE_BORDERLESS);

预定义样式:

  • borderless - 删除表格外边框;

  • no-header - 隐藏表格列的表头;

  • no-horizontal-lines - 删除行之间的水平分隔线;

  • no-vertical-lines - 删除列之间的垂直分隔线;

  • no-stripes - 删除行间隔背景色。

Table 的外观可以使用带 $jmix-table-* 前缀的 SCSS 变量进行自定义。在创建了 自定义主题 之后,可以在可视化编辑器中修改这些变量。

Table 接口方法

  • getSelected()、getSingleSelected() 返回表格中的选定行对应的实体实例。调用 getSelected() 方法来获取实例集合。如果未选择任何内容,则程序将返回空集。如果禁用了 multiselect,应该使用 getSingleSelected() 方法返回一个选定实体,如果没有选择任何内容则返回 null。

  • requestFocus() 方法允许将焦点设置在某一行的具体的可编辑字段上。需要两个参数:表示行的实体实例和列的标识符。请求焦点的示例如下:

    table.requestFocus(item, "count");
  • scrollTo() 方法允许将表格滚动到具体行。需要一个参数:表示行的实体实例。

    滚动条的示例:

    table.scrollTo(item);
  • setItemClickAction() 方法能够定义一个双击表格行时执行的 操作。如果未定义此操作,表格将尝试按以下顺序在其操作列表中查找适当的操作:

    • 由 shortcut 属性指定给 Enter 键的操作;

    • edit 操作

    • view 操作

      如果找到此操作,并且操作具有 enabled=true 属性,则执行该操作。

      下面示例为 XML 中 id 是 tableClick 的 Table 组件设置了 ItemClickAction:

      @Autowired
      private Table<Customer> tableClick;
      
      @Subscribe
      public void onInit(InitEvent event) {
          tableClick.setItemClickAction(new BaseAction("itemClickAction")
                  .withHandler(actionPerformedEvent -> {
                      Customer customer = tableClick.getSingleSelected();
                      if (customer != null) {
                          notifications.create()
                                  .withCaption("Item clicked for: " + customer.getFirstName()+
                                          "" + customer.getLastName())
                                  .show();
                      }
                  }));
      }
  • setEnterPressAction() 方法可以定义按下 Enter 键时执行的操作。如果未定义此操作,则表将尝试按以下顺序在其操作列表中查找适当的操作:

    • 由 setItemClickAction() 方法定义的动作;

    • 由 shortcut 属性指定给 Enter 键的操作;

    • edit 操作;

    • view 操作;

      如果找到此操作,并且操作具有 enabled=true 属性,则执行该操作。

      下面示例为 XML 中 id 是 tableClick 的 Table 组件设置了 ItemClickAction:

      @Autowired
      private Table<Customer> tableClick;
      
      @Subscribe
      public void onInit(InitEvent event) {
          tableClick.setEnterPressAction(new BaseAction("enterPressAction")
                  .withHandler(actionPerformedEvent -> {
                      Customer customer = tableClick.getSingleSelected();
                      if (customer != null) {
                          notifications.create()
                                  .withCaption("Enter pressed for: " + customer.getFirstName()+
                                          "" + customer.getLastName())
                                  .show();
                      }
                  }));
      }
  • The getAggregationResults() 方法返回 聚合 结果的 map,key 为 Table 的列标识符,value 为聚合值。

事件和处理器

如需使用 Jmix Studio 生成处理器的桩代码,需要在界面 XML 描述或者 Jmix UI 层级结构面板选中该组件,然后用 Jmix UI 组件面板的 Handlers 标签页生成。

或者可以使用界面控制器顶部面板的 Generate Handler 按钮。

AggregationDistributionProvider

定义在表格行间按照自定义算法分发聚合值的规则。如果用户在聚合单元格输入值,会根据自定义的算法将值分发到贡献至该聚合值的单元格。只支持 TOP 聚合样式。如果要使得聚合单元格可编辑,需要使用 xml 中 aggregation 元素的 editable 属性。

当创建 provider 时,应当使用 AggregationDistributionContext<E> 对象,包含分发聚合值所需的数据:

  • Column column 合计或分组聚合值变更的列;

  • Object value - 新的聚合值;

  • Collection<E> scope - 一组实体,会受到聚合值的影响;

  • boolean isTotalAggregation 显示合计聚合值或者分组聚合值。

作为示例,我们考虑一个展示预算的表格。用户创建预算种类,并设置每种预算在收入中需要占百分比。下一步,用户在聚合单元格设置收入的总额,然后会按照不同的种类分发。

界面 XML 描述中表格的配置示例:

<table id="budgetTable"
       width="100%"
       aggregatable="true"
       dataContainer="budgetItemsDc">
    <columns>
        <column id="category"/>
        <column id="percent"/>
        <column id="amount">
            <aggregation type="SUM"
                         editable="true"/>
        </column>
    </columns>
</table>

界面控制器示例:

@Install(to = "budgetTable", subject = "aggregationDistributionProvider")
private void budgetTableAggregationDistributionProvider(
        Table.AggregationDistributionContext<BudgetItem> context) {
    Collection<BudgetItem> scope = context.getScope();
    if (scope.isEmpty()) {
        return;
    }

    double value = context.getValue() != null ?
            ((double) context.getValue()) : 0;

    for (BudgetItem budgetItem : scope) {
        budgetItem.setAmount(value / 100 * budgetItem.getPercent());
    }
}
table aggregation budget

如需以编程的方式注册聚合值分配 provider,使用组件的 setAggregationDistributionProvider() 方法。

ColumnCollapseEvent

ColumnCollapseEvent 当 列可见性 变更时发送。

下面示例为 XML 中 id 是 tableCollapsed 的 Table 订阅了该事件:

@Subscribe("tableCollapsed")
public void onTableCollapsedColumnCollapse(Table.ColumnCollapseEvent<Customer> event) {
    notifications.create()
            .withCaption((event.isCollapsed() ? "Collapsed: " : "Expanded: ") +
                    event.getColumn().getCaption())
            .show();
}

如需以编程的方式注册事件处理器,使用组件的 addColumnCollapseListener() 方法。

ColumnReorderEvent

ColumnReorderEvent 当用户重排表格列时发送。

下面示例为 XML 中 id 是 tableReorder 的 Table 订阅了该事件:

@Subscribe("tableReorder")
public void onTableReorderColumnReorder(Table.ColumnReorderEvent<Customer> event) {
    notifications.create()
            .withCaption("Columns were reordered!")
            .show();
}

如需以编程的方式注册事件处理器,使用组件的 addColumnReorderListener() 方法。

ContextHelpIconClickHandler

IconProvider

图标 provider 支持在每行的开头加一个图标:

@Install(to = "tableWithIcons", subject = "iconProvider")
private String tableWithIconsIconProvider(Customer customer) {
    return customer.getEmail() != null ?
            JmixIcon.MAIL_FORWARD.source() : JmixIcon.CANCEL.source();
}
table icon provider

如需以编程的方式注册图标的 provider,使用组件的 setIconProvider() 方法。

ItemDescriptionProvider

当用户鼠标悬停于某个单元格之上时,内容描述 provider 会生成描述提示框。

下面例子中,我们展示了为 tableWithDescription 使用 ItemDescriptionProvider:

@Install(to = "tableWithDescription", subject = "itemDescriptionProvider")
private String tableWithDescriptionItemDescriptionProvider(
        Customer customer, String property) {
    if (property == null)
        return null;
    else if (property.equals("rewardPoints")) {
        return "Reward points are a part of the loyalty program affecting the rating of the " +
                customer.getFirstName() + " " + customer.getLastName();
    } else if (property.equals("level")) {
        switch (customer.getLevel()) {
            case SILVER:
                return "The customer gets special offers from sellers and birthday congratulations";
            case GOLD:
                return "The customer gets 2 coupons with a rating of $ 1";
            case PLATINUM:
                return "The customer gets a coupons with a par value of $ 3";
            case DIAMOND:
                return "The customer gets a coupon with a par value of $ 5";
        }
    }
    return null;
}
table item description

LookupSelectHandler

LookupSelectHandler 是当用户在查找界面选中一行数据按下 Enter 或者双击一行时调用。接收选中的实体集合作为参数。可以定义如下:

@Install(to = "tableLookupSelect", subject = "lookupSelectHandler")
private void tableLookupSelectLookupSelectHandler(Collection<Customer> collection) {
    checkCustomers(collection);
}

如需以编程的方式注册查找界面选择处理器,使用组件的 setLookupSelectHandler() 方法。

SelectionEvent

SelectionEvent 当选择变更时发送。

下面示例为 XML 中 id 是 tableSelectEvent 的 Table 订阅了该事件:

@Autowired
private Table<Customer> tableSelectEvent;

@Subscribe("tableSelectEvent")
public void onTableSelectEventSelection(Table.SelectionEvent<Customer> event) {
    Customer customer = tableSelectEvent.getSingleSelected();
    notifications.create()
            .withCaption("You selected " + customer.getFirstName() +
                    " " + customer.getLastName() + " customer")
            .show();
}

如需以编程的方式注册事件处理器,使用组件的 addSelectionListener() 方法。

StyleProvider

StyleProvider 方法可以设置表格单元格显示样式。表格的每一行和每个单元分别调用这个 provider。如果某一行调用该方法,则第一个参数包含该行显示的实体实例,第二个参数为 null。如果单元格调用该方法,则第二个参数包含单元格显示的属性的名称。

设置样式的示例:

@Install(to = "styledTable", subject = "styleProvider")
private String styledTableStyleProvider(Customer entity, String property) {
    if (property == null) {
        if (Boolean.TRUE.equals(entity.getEmail() != null)) {
            return "customer-has-email";
        }
    } else if (property.equals("level")) {
        switch (entity.getLevel()) {
            case SILVER:
                return "level-silver";
            case GOLD:
                return "level-gold";
            case PLATINUM:
                return "level-platinum";
            case DIAMOND:
                return "level-diamond";
        }
    }
    return null;
}

然后应该在应用程序主题中设置的单元格和行样式。有关创建主题的详细信息,请参阅 主题。在控制器中定义的 provider 返回的样式名称作为 CSS 选择器。示例:

.customer-has-email {
    font-weight: bold;
}

.level-silver {
    background-color: #f2f2f2;
    color: black;
}

.level-gold {
    background-color: #ffda79;
    color: black;
}

.level-platinum {
    background-color: #637497;
    color: white;
}

.level-diamond {
    background-color: #8befff;
    color: black;
}
table style provider

如需以编程的方式注册样式 provider,使用组件的 setStyleProvider() 方法。