2.5.4. Экран редактирования Покупателя со списком Заказов
Займемся задачей отображения списка заказов в окне редактирования покупателя.
Перейдите в секцию Generic UI. Откройте на редактирование экран customer-edit.xml
.
Перейдите на вкладку Designer.
В группе Data components в палитре компонентов найдите Collection и перетащите его в секцию data в иерархии компонентов экрана.
Для контейнера выберите сущность com.company.sales.entity.Order
и её представление _local
. Сгенерируйте loader ID с помощью кнопки .
Добавьте параметр WHERE в сгенерированный запрос JPQL, чтобы загружать только те заказы, которые имеют ссылку на нужного нам покупателя:
select e from sales_Order e where e.customer = :customer
В итоге у вас должен получиться следующий data container для загрузки экземпляров сущности Order
:
<data>
<instance id="customerDc" class="com.company.sales.entity.Customer" view="_local">
<loader/>
</instance>
<collection id="ordersDc" class="com.company.sales.entity.Order" view="_local">
<loader id="ordersDl">
<query><![CDATA[select e from sales_Order e where e.customer = :customer]]></query>
</loader>
</collection>
</data>
Далее, в палитре компонентов найдите компонент Label
. Перетащите этот компонент на панель иерархии компонентов экрана между элементами form
и editActions
. Перейдите на вкладку Properties на панели свойств. В поле value введите значение компонента: Orders
.
Если разрабатываемое приложение предполагает локализацию на несколько языков, используйте кнопку рядом с полем value, чтобы создать новое сообщение |
Перетащите компонент Table
из палитры компонентов на панель иерархии компонентов между label
и editActions
. Выделите компонент в иерархии и перейдите на вкладку Properties. Задайте размеры таблицы: в поле width укажите 300px
, в поле height установите значение 200px
. Из списка доступных источников данных выберите контейнер ordersDc
, после этого в поле id с помощью кнопки сгенерируйте идентификатор таблицы: ordersTable
.
В контекстном меню таблицы выберите Wrap Into > Group Box. Перейдите на вкладку Properties контейнера groupBox
на панели свойств и введите Orders
в поле caption, в поле width укажите 320px
.
В итоге дескриптор экрана customer-edit.xml
на вкладке Text будет выглядеть следующим образом:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<window xmlns="http://schemas.haulmont.com/cuba/screen/window.xsd" caption="msg://editorCaption" focusComponent="form"
messagesPack="com.company.sales.web.customer">
<data>
<instance id="customerDc" class="com.company.sales.entity.Customer" view="_local">
<loader/>
</instance>
<collection id="ordersDc" class="com.company.sales.entity.Order" view="_local">
<loader id="ordersDl">
<query><![CDATA[select e from sales_Order e where e.customer = :customer]]></query>
</loader>
</collection>
</data>
<dialogMode height="600" width="800"/>
<layout expand="editActions" spacing="true">
<form id="form" dataContainer="customerDc">
<column width="250px">
<textField id="nameField" property="name"/>
<textField id="emailField" property="email"/>
</column>
</form>
<groupBox caption="Orders">
<table id="ordersDcTable" dataContainer="ordersDc" height="200px" width="300px">
<columns>
<column id="date"/>
<column id="amount"/>
</columns>
</table>
</groupBox>
<hbox id="editActions" spacing="true">
<button action="windowCommitAndClose"/>
<button action="windowClose"/>
</hbox>
</layout>
</window>
Откройте контроллер экрана CustomerEdit
. Кнопки и на панели с номерами строк помогут вам быстро переключаться между дескриптором и контроллером экрана.
Для начала давайте отключим автоматическую загрузку данных. Для этого удалите аннотацию @LoadDataBeforeShow
из исходного кода.
Инжектируйте loader для заказов в класс контроллера:
@Inject
private CollectionLoader<Order> ordersDl;
Затем подпишитесь на событие BeforeShowEvent
, чтобы указать значение параметра customer
в запросе ordersDl
. Это можно сделать, нажав Alt+Insert и выбрав Subscribe to Event в появившемся меню Generate.
@UiController("sales_Customer.edit")
@UiDescriptor("customer-edit.xml")
@EditedEntityContainer("customerDc")
public class CustomerEdit extends StandardEditor<Customer> {
@Inject
private CollectionLoader<Order> ordersDl;
@Subscribe
protected void onBeforeShow(BeforeShowEvent event) {
ordersDl.setParameter("customer", getEditedEntity());
getScreenData().loadAll();
}
}
Этот метод будет загружать связанные экземпляры сущности Order
.