Runtime View Templates
Runtime view templates let you generate standard list and detail views from templates declared on entity metadata instead of creating them manually at design time. You annotate an entity class with @ListViewTemplate and/or @DetailViewTemplate, and the framework generates the corresponding views, routes, and menu items when the application starts.
This is useful for quickly exposing entities in the UI – for example, lookup or reference data – without writing view classes and XML descriptors for each of them. The generated views are registered just like regular views: they participate in view inference, can be opened by id or route, and can serve as primary list and detail views for the entity.
| Runtime view templates are currently in the experimental state. The API and the built-in templates can change significantly in the next Jmix release. |
Getting Started
To generate a list and a detail view for an entity, annotate its class:
@ListViewTemplate(parentMenu = "application")
@DetailViewTemplate
@JmixEntity
@Entity
@Table(name = "PRODUCT")
public class Product {
With these two annotations, the framework generates at startup:
-
a list view with the id
Product.list, displaying a dataGrid with the entity properties, a genericFilter, pagination, and Create, Edit, Remove actions; -
a detail view with the id
Product.detail, displaying a formLayout with editable fields for the entity properties; -
a menu item under the
applicationmenu that opens the list view.
The views use the built-in templates, which decide what to render based on the entity’s properties. No XML descriptors or view classes are created in your project.
@ListViewTemplate
@ListViewTemplate declares a generated list view for the annotated entity:
@ListViewTemplate(
path = "io/jmix/flowui/view/template/list-view.ftl",
viewId = "Supplier.list",
viewRoute = "suppliers",
viewTitle = "Suppliers",
parentMenu = "application",
templateParams = """
{
"includeProperties": ["createdBy", "createdDate"],
"excludeProperties": ["internalNote"]
}
"""
)
In addition to the common attributes, it supports:
-
lookupComponentId– the id of the component used as the lookup component. Defaults todataGrid.
@DetailViewTemplate
@DetailViewTemplate declares a generated detail view for the annotated entity:
@DetailViewTemplate(
viewId = "Supplier.detail",
viewRoute = "suppliers",
viewTitle = "Supplier",
editedEntityContainerId = "entityDc"
)
In addition to the common attributes, it supports:
-
editedEntityContainerId– the id of the data container holding the edited entity, see @EditedEntityContainer. Defaults toentityDc.
Common Attributes
Both annotations share the following attributes:
| Attribute | Description |
|---|---|
|
Resource path to a Freemarker XML descriptor template. If omitted, the corresponding built-in template is used. |
|
A JSON object with additional parameters passed to the template. See Built-in Templates for the parameters the built-in templates support. |
|
The id of the parent menu item for the generated menu item. If empty, no menu item is created. If it points to a missing menu item, a new root menu item is created automatically. |
|
The id of the generated view. |
|
The route path of the generated view. |
|
The page title of the generated view. |
Default Values
When the optional attributes are omitted, the framework derives them from the entity name <entityName>:
@ListViewTemplate |
@DetailViewTemplate |
|
|---|---|---|
|
|
|
|
|
|
Routing
The route is resolved from viewRoute as follows:
-
For a list view,
viewRouteis used as-is. -
For a detail view,
viewRouteis treated as a base route and always becomes…/:id. -
If
viewRouteis empty, it is derived fromviewId.
In the Supplier example above, the list view route is suppliers and the detail view route is suppliers/:id.
Built-in Templates
When path is not specified, the framework uses built-in templates that generate the view content from the entity’s properties:
-
the list view template renders a
dataGridwith a column per property, agenericFilter, pagination, and list actions; -
the detail view template renders a
formLayoutwith a field per property.
The built-in templates are located at:
-
io/jmix/flowui/view/template/list-view.ftl -
io/jmix/flowui/view/template/detail-view.ftl
Property Filtering
By default, the built-in templates include direct single-value properties and exclude:
-
system properties;
-
properties annotated as secret;
-
id, version, and generated properties;
-
audit and soft-deletion properties.
Built-in property filtering supports only direct single-value datatype, enum, association, and composition properties. It does not support collection-valued datatype properties, embedded properties, or dotted property paths such as customer.name.
You can adjust the set of displayed properties using two keys in templateParams:
-
includeProperties– restores excluded but supported direct properties; -
excludeProperties– removes properties; it is applied last and takes precedence overincludeProperties.
In the Supplier example, the createdBy and createdDate audit properties are restored, while internalNote is excluded:
@ListViewTemplate(
path = "io/jmix/flowui/view/template/list-view.ftl",
viewId = "Supplier.list",
viewRoute = "suppliers",
viewTitle = "Suppliers",
parentMenu = "application",
templateParams = """
{
"includeProperties": ["createdBy", "createdDate"],
"excludeProperties": ["internalNote"]
}
"""
)
Composition Collections
If an entity used in a @DetailViewTemplate has composition *-to-many properties, the generated detail view renders a tabSheet instead of a single form:
-
the first General tab holds the form with the single-value fields;
-
each composition collection gets its own tab with a
dataGridproviding Create, Edit, and Remove actions.
The Create and Edit actions open the line entity’s own detail view in a dialog, so line entities are expected to also carry @DetailViewTemplate. The inverse attribute of a composition collection – the child’s reference back to the parent – is excluded by default both from the master’s columns and from the line entity’s detail form. You can restore it with includeProperties.
The example below defines a master entity with a composition collection and the corresponding line entity:
@ListViewTemplate(parentMenu = "application")
@DetailViewTemplate
@JmixEntity
@Entity
@Table(name = "INVOICE")
public class Invoice {
@Composition
@OneToMany(mappedBy = "invoice")
private List<InvoiceItem> items;
@DetailViewTemplate
@JmixEntity
@Entity
@Table(name = "INVOICE_ITEM")
public class InvoiceItem {
Only composition collections are supported. Association collections, element collections, and embedded attributes are not rendered.
Entities without composition collections render a plain formLayout.
Custom Templates
To fully control the generated view content, provide your own Freemarker template in the path attribute. The template is a .ftl file located on the classpath that produces a standard view XML descriptor.
The following variables are available in the template model:
-
entityMetaClass– theMetaClassof the annotated entity; -
viewTitle– the resolved view title; -
templateHelper– a helper that returns the filtered properties (getProperties) and composition collection properties (getCollectionProperties); -
componentXmlFactory– a factory that produces the XML fragment for a property’s edit component; -
all keys from
templateParams, includingincludePropertiesandexcludeProperties.
You can use the built-in templates as a starting point.
Menu Integration
If the parentMenu attribute of @ListViewTemplate or @DetailViewTemplate is set, a menu item that opens the generated view is appended to the specified parent menu after the standard XML menu definitions are loaded. If parentMenu is empty, no menu item is created. If it points to a missing menu item, a new root menu item is created automatically.