渲染器

该章节介绍 UI 组中可以使用的通用渲染器 API,例如 ComponentRendererLitRendererFragmentRenderer。对于预定义的 XML 渲染器,支持的属性,以及特定组件的示例,请参考对应组件的文档。

渲染器特别适合以下场景:

  • 增强的可视化展示:能够包含纯文本之外的视觉元素,例如图标、图像、进度条或其他元素,使数据更容易理解和吸引人。因此可以提升整体的用户体验和 UI 所表达意思的清晰度。

    radio button group renderer
  • 按条件渲染:渲染器可以根据数据值或其他上下文信息更改视觉展示。例如,为成功的记录显示绿色对勾标记,为失败的记录显示红色对勾标记。

    renderer 2
  • 复杂的布局:在需要提供复杂渲染布局的情况下,自定义渲染器可以提供以非标准方式排列和显示数据的灵活性。例如可以在单个组件单元中组合多个 UI 元素或创建完全自定义的布局。

    renderer 3
如果只需修改值的显示方式,例如日期或数字的显示方式,可以使用 格式化器

组件渲染器

ComponentRenderer 使用 UI 组件而非纯文本来渲染内容。可以通过 setRenderer() 以编程方式设置,或使用 @Supply 从控制器中提供。

ComponentRenderer 会为渲染的内容创建 UI 组件,渲染大量数据时,可能影响性能。如果只需要渲染类似 HTML 的内容,请使用 LitRenderer

ComponentRenderer 可以通过不同方式创建,具体取决于开发者希望如何创建和更新组件。以下示例展示了不同的方法。

单回调

适合场景:使用单一方法即可从数据项生成新的组件。

@Supply(to = "selectWithRenderer", subject = "renderer") (1)
private ComponentRenderer<Button, Department> selectWithRendererRenderer() {
    return new ComponentRenderer<>(item -> { (2)
        Button button = uiComponents.create(Button.class); (3)
        button.setText(item.getName());
        button.setIcon(VaadinIcon.DESKTOP.create());
        return button; (4)
    });
}
1 @Supply 将渲染器与 selectWithRenderer 组件绑定。
2 方法接收当前数据项。
3 组件实例在同一个回调中创建和配置。
4 方法返回当前数据项的组件。

分开创建与绑定

适合场景:当组件的创建和数据绑定需要分开处理时。

@Supply(to = "dataGridCheckbox.active", subject = "renderer") (1)
private Renderer<User> dataGridCheckboxActiveRenderer() {
    return new ComponentRenderer<>(
            () -> {
                JmixCheckbox checkbox = uiComponents.create(JmixCheckbox.class); (2)
                checkbox.setReadOnly(true); (3)
                return checkbox; (4)
            },
            (checkbox, item) -> checkbox.setValue(item.getActive()) (5)
    );
}
1 @Supply 将渲染器与 dataGridCheckboxactive 列绑定。
2 这个 lambda 方法是 supplier 方法,创建一个 JmixCheckbox 组件实例。
3 复选框被设置为只读模式。
4 supplier 返回组件实例。
5 consumer 方法接收组件和当前项,然后从 item.getActive() 获取复选框的值并设置。

显式更新

适合场景:当数据项的更新比之前的示例需要更多的控制时。更新回调可以使用当前的组件实例,或将其替换为一个新的组件。

@Supply(to = "dataGridStatus.status", subject = "renderer")
private Renderer<User> createUpdatableStatusRenderer() {
    return new ComponentRenderer<>(
            item -> {
                Span span = uiComponents.create(Span.class); (1)
                updateSpanBadge(span, item); (2)
                return span; (3)
            },
            (component, item) -> {
                if (item.getOnboardingStatus() == null) { (4)
                    updateUnknownStatus(component); (5)
                    return component; (6)
                } else {
                    return createStatusBadge(item); (7)
                }
            }
    );
}
1 creation 回调创建初始的 Span 组件实例。
2 设置初始组件值并配置为当前数据的徽章样式。
3 creation 回调返回组件。
4 update 回调检查当前数据是否有状态值。
5 如果值缺失,回调更新当前组件实例。
6 当前组件保持不变并返回。
7 如果值存在,回调为该项创建并返回一个新组件。

可在支持 ComponentRenderer 的 UI 组件中查看更多示例:

LitRenderer

LitRenderer 使用 HTML 和 Lit 的数据绑定语法,能高效地渲染内容。是组件渲染器的轻量级替代方案,在频繁渲染或更新多个组件时,仍然有良好的性能。

LitRenderer 支持定义一个 HTML 模板,并绑定模板中的变量和实体属性:

@Supply(to = "dataGridLit.userInfo", subject = "renderer")
private Renderer<User> dataGridLitUserInfoRenderer() {
    return LitRenderer.<User>of("${item.firstName}<br>${item.lastName}<br>${item.email}")
            .withProperty("firstName", User::getFirstName)
            .withProperty("lastName", User::getLastName)
            .withProperty("email", User::getEmail);
}
renderer 5

下列 UI 组件可以使用 LitRenderer

Fragment 渲染器

virtualListdataGrid 等组件的渲染器可以通过 fragments 定义。XML 中使用特定的 fragmentRenderer 元素指定渲染器。

与普通 fragment 一样,fragmentRenderer 也是通过 XML 和 Java 控制器定义。

  1. 创建 FragmentRenderer 的 XML

    XML 中包含可选的 instanceContainer(实体实例数据容器):

    <fragment xmlns="http://jmix.io/schema/flowui/fragment">
        <data>
            <instance id="userDc" class="com.company.onboarding.entity.User">
                <loader id="userDl"/>
                <fetchPlan extends="_base"/>
            </instance>
        </data>
        <content>
            <hbox>
                <icon icon="ANGLE_DOUBLE_RIGHT"/>
                <formLayout id="form" dataContainer="userDc">
                    <textField property="username" readOnly="true"/>
                    <textField property="firstName" readOnly="true"/>
                    <textField property="lastName" readOnly="true"/>
                    <textField property="email" readOnly="true"/>
                </formLayout>
            </hbox>
        </content>
    </fragment>
    如果未定义实例数据容器,则可以用 FragmentRenderer.getItem() 方法处理渲染。
  2. 创建 FragmentRenderer Java 控制器

    Fragment 渲染器类需要继承自 FragmentRenderer,并使用泛型参数指定组件的根元素和渲染的实体,示例:

    @FragmentDescriptor("user-fragment.xml") (1)
    @RendererItemContainer("userDc") (2)
    public class UserFragment extends FragmentRenderer<HorizontalLayout, User> {
    }
    1 @FragmentDescriptor 注解指定一个字符串值,指向 fragment 的 XML 文件路径。
    2 @RendererItemContainer 注解用于指定所渲染实体的数据容器。
  3. 在视图中使用 FragmentRenderer

    在需要使用 fragment 渲染的组件中添加 fragmentRenderer 元素。该元素需要指定一个 class 属性,需配置为继承自 io.jmix.flowui.fragmentrenderer.FragmentRenderer 的渲染器类的全限名称。

    <virtualList itemsContainer="usersDc">
        <fragmentRenderer
                class="com.company.onboarding.view.component.virtuallist.UserFragment"/>
    </virtualList>

    如需在 Jmix Studio 中添加 fragmentRenderer,请在视图 XML 或 Jmix UI 结构面板中选择 UI 组件,然后点击属性面板中的 Add→FragmentRenderer

    fragmentRenderer 与普通 fragment 一样,也支持 传参

renderer 6

以下 UI 组件支持 fragmentRenderer