The following example shows how to display Orders on a lazy tab of the Customer master-detail screen.
The data model is as usual: Order has a many-to-one reference to Customer.
<window xmlns="http://jmix.io/schema/ui/window"
xmlns:c="http://jmix.io/schema/ui/jpql-condition"
caption="msg://customerBrowse.caption"
focusComponent="table">
<data>
<collection id="customersDc"
class="com.company.demo.entity.Customer">
<fetchPlan extends="_base"/>
<loader id="customersDl">
<query>
<![CDATA[select e from Customer e]]>
</query>
</loader>
</collection>
<instance id="customerDc"
class="com.company.demo.entity.Customer">
<fetchPlan extends="_base"/>
<loader/>
</instance>
<!-- this is lazily loaded data -->
<collection id="ordersDc" class="com.company.demo.entity.Order">
<fetchPlan extends="_base"/>
<loader id="ordersDl">
<query><![CDATA[select e from Order_ e where e.customer = :customer]]></query>
</loader>
</collection>
</data>
<facets>
<!-- remove automatic loading -->
<!-- <dataLoadCoordinator auto="true"/>-->
<screenSettings id="settingsFacet" auto="true"/>
</facets>
<!-- ... -->
<layout>
<!-- ... -->
<vbox id="editBox" height="100%" margin="false,false,false,true" expand="tabSheet" spacing="true">
<tabSheet id="tabSheet">
<tab id="mainTab" caption="Main" margin="true">
<scrollBox id="fieldGroupBox">
<form id="form" dataContainer="customerDc">
<column width="350px">
<textField id="nameField" property="name"/>
<textField id="emailField" property="email"/>
</column>
</form>
</scrollBox>
</tab>
<tab id="ordersTab" caption="Orders" lazy="true" margin="true" expand="ordersTable">
<table id="ordersTable" width="100%" dataContainer="ordersDc">
<actions>
<action id="create" type="create"/>
<action id="edit" type="edit"/>
<action id="remove" type="remove"/>
</actions>
<buttonsPanel alwaysVisible="true">
<button id="ordersTableCreateBtn" action="ordersTable.create"/>
<button id="ordersTableEditBtn" action="ordersTable.edit"/>
<button id="ordersTableRemoveBtn" action="ordersTable.remove"/>
</buttonsPanel>
<columns>
<column id="num"/>
<column id="date"/>
</columns>
</table>
</tab>
</tabSheet>
<!-- ... -->
@UiController("Customer.browse")
@UiDescriptor("customer-browse.xml")
@LookupComponent("table")
public class CustomerBrowse extends MasterDetailScreen<Customer> {
@Autowired
private CollectionContainer<Customer> customersDc;
@Autowired
private CollectionLoader<Customer> customersDl;
@Autowired
private CollectionLoader<Order> ordersDl;
private boolean ordersTabInitialized;
@Subscribe
public void onBeforeShow(BeforeShowEvent event) {
// on screen opening, trigger loaders selectively
customersDl.load();
}
@Subscribe(id = "customersDc", target = Target.DATA_CONTAINER)
public void onCustomersDcItemChange(InstanceContainer.ItemChangeEvent<Customer> event) {
// refresh data on lazy tab if it was selected by the user
if (ordersTabInitialized) {
refreshOrders();
}
}
@Subscribe("tabSheet")
public void onTabSheetSelectedTabChange(TabSheet.SelectedTabChangeEvent event) {
if (event.getSelectedTab().getName().equals("ordersTab") && !ordersTabInitialized) {
ordersTabInitialized = true;
refreshOrders();
// get components located on the lazy tab
Table<Order> ordersTable = (Table) getWindow().getComponentNN("ordersTable");
CreateAction<Order> orderCreateAction = (CreateAction) ordersTable.getActionNN("create");
// initalize new order with current cuatomer
orderCreateAction.setInitializer((Order order) -> {
order.setCustomer(getEditedEntity());
});
// enable creating orders only for already existing customers
orderCreateAction.addEnabledRule(() -> !creating);
}
}
private void refreshOrders() {
ordersDl.setParameter("customer", customersDc.getItemOrNull());
ordersDl.load();
}
}
The entire project:
demo.zip (87.9 KB)
Regards,
Konstantin