원클릭으로
jmix-create-detail-view
Create a Jmix Flow UI detail view with XML descriptor, save-close action, messages, and policies.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Create a Jmix Flow UI detail view with XML descriptor, save-close action, messages, and policies.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Open a Jmix entity detail view from a button/action and refresh related data after save.
Add Jmix entity lifecycle event listeners to perform additional actions with saved or loaded entities.
Add complete Jmix message keys for entities, enums, views, actions, and validation text.
Configure or audit Jmix fetch plans in XML views, fragments, DataManager loads, repositories, and entity events when loading references, avoiding N+1 queries, fixing unfetched attribute errors, or tuning data loading.
Add inline editable parent-child composition UI to a Jmix detail view, when a parent entity owns child records edited via a property-bound collection container (no query loader).
Create or change Jmix DTO entities and other non-persistent transfer models for UI data containers, REST/API payloads, custom data stores, external data, or calculated read models.
| name | jmix-create-detail-view |
| description | Create a Jmix Flow UI detail view with XML descriptor, save-close action, messages, and policies. |
Use this skill when creating a create/edit view for one entity.
Both produce valid Java/XML — compileJava is green — and then throw
when the view is opened. compileJava is BLIND to *-view.xml; only a
Jmix-aware inspection catches them statically, and the mechanical checks
do NOT cover these two. With no inspection, get them right BY
CONSTRUCTION from the WRONG/RIGHT examples below:
An enum attribute is NEVER entityComboBox. entityComboBox
is for ENTITY references; binding it to an enum (with or without a
made-up enumClass attribute) throws IllegalStateException: Range is enumeration at render. There is no enumClass attribute on
entityComboBox. For a Jmix enum property use a plain <comboBox>
or <select> — Jmix auto-populates it from the enum:
<!-- WRONG: <entityComboBox property="category" enumClass="...SomeEnum"/> -->
<comboBox id="categoryField" property="category"/> <!-- enum: just bind the property -->
itemsQuery MUST wrap its JPQL in a nested <query> element, and that
query MUST reference :searchString (the combo passes it for type-ahead).
Raw CDATA directly under <itemsQuery> throws
GuiDevelopmentException: Nested 'query' element is missing; a query that
ignores :searchString throws DevelopmentException: Parameter 'searchString' is not used in the query at dropdown fetch. See "Reference Fields" below for
the correct shape.
These are two DIFFERENT things. Do not conflate them.
Read-only OPEN MODE is set by the LIST view's open action:
list_read instead of list_edit. list_read is an open MODE
(read-only at runtime), not a readOnly descriptor. Users opening an
existing row see a non-editable form; new entities still open in
writable mode through list_create.
Read-only DESCRIPTOR would mean every form field is hard-coded
readOnly="true" and the detail view has no save action — only
detail_close. This makes the view ALWAYS read-only, even for new
entities. It CANNOT create entities and CANNOT save edits.
"The list opens records in read mode" or "the detail view is opened
with the read action" — both phrasings call for read-only OPEN MODE
on the LIST side. The detail XML must still be a normal writable
descriptor with detail_saveClose and editable fields. Jmix flips
fields to read-only at runtime based on the open mode.
A detail view without a save action is broken for create flows. Always declare both:
<actions>
<action id="saveCloseAction" type="detail_saveClose"/>
<action id="closeAction" type="detail_close"/>
</actions>
and use editable form components (textField, comboBox,
entityComboBox, etc.) without hard-coded readOnly="true" unless
a specific attribute is permanently read-only in domain terms (e.g.
audit timestamps).
view/<entityname>/.StandardDetailView<Entity>.@Route(value = ".../:id", layout = MainView.class).@ViewController(id = "Entity.detail").@ViewDescriptor(path = "entity-detail-view.xml").@EditedEntityContainer("<entity>Dc").dataLoadCoordinator, typed form fields, detail_saveClose, and detail_close.itemsContainer, or itemsQuery.InitEntityEvent for UI-only defaults ONLY. A required persistent default must be set at the ENTITY layer (field initializer / @PostConstruct / EntitySavingEvent) — NOT in an InitEntityEvent alone, NOT in a service, NOT in EntityChangedEvent (it fires after persist and cannot satisfy @NotNull). Tests save via DataManager and bypass the view — see jmix-create-entity (required-field defaults).@ViewPolicy(viewIds = "Entity.detail") — declared on a method of a @ResourceRole interface (the annotation is @Target(METHOD)), not on the view controller. The annotation has no value() member: @ViewPolicy("...") does not compile; use viewIds = "..." (or viewClasses = ...). See jmix-create-resource-role.@Route(value = "customers/:id", layout = MainView.class)
@ViewController(id = "Customer.detail")
@ViewDescriptor(path = "customer-detail-view.xml")
@EditedEntityContainer("customerDc")
public class CustomerDetailView extends StandardDetailView<Customer> {
}
<view xmlns="http://jmix.io/schema/flowui/view"
title="msg://customerDetailView.title"
focusComponent="form">
<data>
<instance id="customerDc" class="com.company.app.entity.Customer">
<fetchPlan extends="_base"/>
<loader id="customerDl"/>
</instance>
</data>
<facets>
<dataLoadCoordinator auto="true"/>
</facets>
<actions>
<action id="saveCloseAction" type="detail_saveClose"/>
<action id="closeAction" type="detail_close"/>
</actions>
<layout>
<formLayout id="form" dataContainer="customerDc">
<textField id="nameField" property="name"/>
</formLayout>
<hbox id="detailActions">
<button id="saveAndCloseButton" action="saveCloseAction"/>
<button id="closeButton" action="closeAction"/>
</hbox>
</layout>
</view>
Choose form components by property type:
| Property type | Component |
|---|---|
String short text | textField |
String long text | textArea |
Integer | integerField |
Long | integerField or numberField according to project usage |
BigDecimal | bigDecimalField |
Boolean | checkbox |
LocalDate | datePicker |
LocalDateTime | dateTimePicker |
| Jmix enum | select or comboBox |
| Entity reference | entityComboBox or entityPicker |
Do not expose technical fields (id, version) in user-facing forms. Hide parent/default fields only when they are initialized elsewhere.
After creating or editing the descriptor, inspect each field:
Integer is not a textField; use integerField.BigDecimal is not a textField; use bigDecimalField.If an existing project uses a different compiled pattern for a type, follow the existing pattern and keep it consistent.
For @ManyToOne and other entity references, pick the pattern by candidate-set characteristics:
entityComboBox with itemsQuery — PREFERRED. Lazy-loading: the JPQL runs against the database on every type-ahead, fetching only matching candidates. Use this for any non-trivial candidate set.entityComboBox with itemsContainer — for small, fixed sets that fit comfortably in memory and rarely change. Preloaded once at view open.entityPicker with lookup and clear actions — when users need a full lookup screen. Use the literal standard action ids entity_lookup and entity_clear (do not invent ids).itemsQuery — the correct shapeThe combo passes a searchString parameter for type-ahead, so the
JPQL MUST like :searchString; ignoring it throws DevelopmentException: Parameter 'searchString' is not used in the query at dropdown fetch.
The JPQL must use the JPA/Jmix entity name, not the database table
name.
<entityComboBox id="refField" property="ref">
<itemsQuery class="com.company.app.entity.Ref">
<query>
<![CDATA[
select e from Ref e
where e.name like :searchString
order by e.name
]]>
</query>
</itemsQuery>
</entityComboBox>
itemsQuery does NOT auto-bind :container_* / :component_*
parameters — when the reference list depends on another component or
container, use itemsContainer with a regular loader instead (see
below).
itemsContainer — when the set is small or container-dependentDeclare a <collection> for the candidate entities and point the combo
at it:
<data>
<instance id="<entity>Dc" class="com.company.app.entity.<Entity>">
<fetchPlan extends="_base">
<property name="ref" fetchPlan="_instance_name"/>
</fetchPlan>
<loader id="<entity>Dl"/>
</instance>
<collection id="refsDc" class="com.company.app.entity.Ref">
<fetchPlan extends="_instance_name"/>
<loader id="refsDl">
<query><![CDATA[select e from Ref e order by e.name]]></query>
</loader>
</collection>
</data>
...
<entityComboBox id="refField" property="ref" itemsContainer="refsDc"/>
<dataLoadCoordinator auto="true"/> loads refsDc at open. Use this
when the candidate set is small enough to fit in memory, or when the
loader takes a :container_* / :component_* parameter that
itemsQuery cannot bind.
Before finishing, verify that saved reference entities can appear in the component data provider. If a field is required, do not leave a reference component without a working item source or lookup action.
For cross-field/manual validation, add a @Subscribe handler on ValidationEvent and report failures via event.getErrors().add("..."); for programmatic checks (e.g. before a custom save) use the ViewValidation bean (validateUiComponents, showValidationErrors).
detail_saveClose.textField for numeric, date/time, boolean, or reference properties.itemsContainer, or verified itemsQuery.@Table names in itemsQuery.itemsQuery with unresolved container_ or component_ parameters.