Renderers
This section describes how to customize the rendering of UI components like comboBox, dataGrid, checkboxGroup, select and others using custom renderers in Jmix. Custom renderers allow developers to control the visual representation of data within these components, tailoring the UI to specific application requirements. This is particularly useful for:
-
Enhanced visual representation: They enable the inclusion of visual elements beyond plain text, such as icons, images, progress bars, or others, to make data more easily understandable and engaging. This can improve the overall user experience and clarity of the UI.
-
Conditional rendering: Renderers can implement logic to change the visual appearance based on the data’s value or other contextual information. For instance, a renderer might display a green checkmark for successful records and a red checkmark for failed ones.
-
Complex layouts: For situations requiring more complex visual layouts than the default rendering offers, custom renderers provide the flexibility to arrange and display data in non-standard ways. This could involve combining several UI elements within a single component cell or creating entirely custom layouts.
In essence, renderers in Jmix empower developers to move beyond the basic display capabilities of the default UI components, creating a more tailored and user-friendly interface that effectively communicates data to the end-user.
If you need to simply format data (for example, change the way a date or number appears), use a formatter. |
Predefined XML Renderer
Jmix provides predefined XML renderers for DataGrid and TreeDataGrid columns to simplify common formatting and display table data:
They accept a format
string. For example:
<column property="joiningDate">
<localDateRenderer format="MMM dd, yyyy"/>
</column>
To add a renderer in Jmix Studio, select the |
Component Renderer
Component renderers provide a mechanism for rendering data within UI components using other UI components.
A component renderer takes data as input and generates a UI component (such as a checkBox, or image) to represent that data. This generated component is then used by the parent UI component (for example, a dataGrid column) to display the data. This approach is particularly useful when you need to visually represent data using more than just simple text formatting.
While simple to implement, component renderers can negatively impact performance, especially with large datasets, because they create a separate UI component for each data item. |
To create a renderer use the setRenderer()
method or @Supply
annotation.
To generate a renderer handler method in Jmix Studio, select the component or grid column, go to the Handlers tab of the Jmix UI inspector panel and double-click the relevant row. Also, you can use the Generate Handler action available in the top panel of the view class and through the Code → Generate menu (Alt+Insert / Cmd+N).
|
As an example, let’s consider adding a renderer to display a boolean value using a checkBox
in a dataGrid
.
Select the active
column, switch to the Handlers tab of the Jmix UI inspector and double-click the renderer
handler method:
Implement the dataGridCheckboxActiveRenderer
method:
@Supply(to = "dataGridCheckbox.active", subject = "renderer")
private Renderer<User> dataGridCheckboxActiveRenderer() {
return new ComponentRenderer<>(
() -> {
JmixCheckbox checkbox = uiComponents.create(JmixCheckbox.class); (1)
checkbox.setReadOnly(true); (2)
return checkbox; (3)
},
(checkbox, user) -> checkbox.setValue(user.getActive()) (4)
);
}
1 | The JmixCheckbox component instance is created using the UiComponents factory. |
2 | Sets checkbox to read-only mode, preventing users from directly changing its state. |
3 | The renderer returns the newly created, read-only checkbox to be shown in the column cells. |
4 | Lambda expression that configures the checkbox’s value. It’s a consumer that takes two parameters: the checkbox component and a User instance. It sets the checkbox’s value based on the active attribute of the User entity. |
Examples of custom rendering for various UI components are provided in the relevant sections of the Jmix documentation:
LitRenderer
LitRenderer
renders content using HTML and Lit’s data-binding syntax; it’s more lightweight than component-based renderers.
LitRenderer
allows you to define an HTML template and bind properties from an entity to template variables:
@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);
}
LitRenderer renders efficiently and is ideal for high-performance applications needing frequent updates. Its lightweight design makes it well-suited for applications with many components or dynamic content.
|
You can use LitRenderer
in the following UI components:
Fragment Renderer
Renderers for virtualList, dataGrid and other components can be defined using fragments. A special fragmentRenderer
XML element is used to declaratively describe a renderer.
Like regular fragments, a fragmentRenderer
is defined using a descriptor and a Java controller.
-
Create FragmentRenderer XML-descriptor
The descriptor can contain an optional instanceContainer for the entity that will be used by the renderer.
<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>
If the instance container is not defined, you can use the FragmentRenderer.getItem()
method to handle rendering. -
Create FragmentRenderer Java Controller
The fragment renderer class should extend the
FragmentRenderer
base class with type parameters indicating the root component and rendered entity, for example:@FragmentDescriptor("user-fragment.xml") (1) @RendererItemContainer("userDc") (2) public class UserFragment extends FragmentRenderer<HorizontalLayout, User> { }
1 The @FragmentDescriptor
annotation specifies a string value that is a path to an XML file which is used for the fragment initialization.2 The @RendererItemContainer
annotation is used to specify the data container that accepts the rendered entity. -
Use FragmentRenderer in a View
Select the component where you want to render items and include the
fragmentRenderer
element. This element requires aclass
attribute specifying the fully qualified name (FQN) of a class extending the abstractio.jmix.flowui.fragmentrenderer.FragmentRenderer
class.<virtualList itemsContainer="usersDc"> <fragmentRenderer class="com.company.onboarding.view.component.virtuallist.UserFragment"/> </virtualList>
To add a
fragmentRenderer
in Jmix Studio, select the UI component in the view descriptor XML or in the Jmix UI structure panel and click on the Add→FragmentRenderer button in the Jmix UI inspector panel.The
fragmentRenderer
element also supports loading properties, just like thefragment
element.
You can use fragmentRenderer
in the following UI components: