3.5.2.1.11. DataGrid
В этом разделе:
DataGrid
, подобно компоненту Table, позволяет выводить информацию в виде таблицы, сортировать её, вызывать действия для выбранных строк, а также более эффективно управлять строками и колонками таблицы за счёт отложенной загрузки данных при прокрутке.
XML-имя компонента: dataGrid
.
Пример описания компонента в XML-дескрипторе экрана:
<data>
<collection id="ordersDc" class="com.company.sales.entity.Order" view="order-with-customer">
<loader id="ordersDl">
<query>
<![CDATA[select e from sales_Order e order by e.date]]>
</query>
</loader>
</collection>
</data>
<layout>
<dataGrid id="ordersDataGrid" dataContainer="ordersDc" height="100%" width="100%">
<columns>
<column id="date" property="date"/>
<column id="customer" property="customer.name"/>
<column id="amount" property="amount"/>
</columns>
</dataGrid>
</layout>
В данном примере атрибут id
- это идентификатор колонки, а атрибут property
содержит имя атрибута сущности, содержащейся в источнике данных, который следует использовать в качестве данных для колонки.
Если вы хотите указать источник данных для таблицы программно в контроллере экрана, используйте атрибут metaClass вместо декларативного указания значения dataContainer в XML.
Элементы dataGrid
-
columns
- элемент, определяющий набор колонокDataGrid
. Если не задан, то столбцы таблицы будут автоматически определены из атрибутов представления, используемого при загрузке данных из контейнера данных. Элементcolumns
имеет следующие атрибуты:-
includeAll
– загружает все атрибуты представления, используемого при загрузке данных из контейнера данных.В приведенном ниже примере мы покажем все атрибуты из представления, используемого в
customersDc
. Если представление содержит системные свойства, они также будут показаны.<dataGrid id="dataGrid" width="100%" height="100%" dataContainer="customersDc"> <columns includeAll="true"/> </dataGrid>
Если представление сущности содержит ссылочный атрибут, этот атрибут выводится в соответствии с его шаблоном @NamePattern. Если вы хотите показать какой-то конкретный атрибут, он должен быть определен в представлении, а также в элементе
column
:<columns includeAll="true"> <column id="address.street"/> </columns>
Если представление не указано, атрибут
includeAll
загрузит все атрибуты из данной сущности и ее предков.
-
exclude
– разделенный запятыми список атрибутов, которые не должны быть загружены вDataGrid
.В приведенном ниже примере мы покажем все атрибуты, за исключением атрибутов
name
иorder
:<dataGrid id="dataGrid" width="100%" height="100%" dataContainer="customersDc"> <columns includeAll="true" exclude="name, order"/> </dataGrid>
Каждая колонка описывается во вложенном элементе
column
со следующими атрибутами:-
id
- необязательный атрибут, содержит строковый идентификатор колонки. Если не задан, в качестве идентификатора колонки будет использоваться строковое значение атрибутаproperty
. В этом случае проставление атрибутаproperty
является обязательным, в противном случае будет брошено исключениеGuiDevelopmentException
. Атрибутid
по-прежнему является обязательным для колонки, создаваемой программно.
-
property
- необязательный атрибут, содержит название атрибута сущности, выводимого в колонке. Может быть как непосредственным атрибутом сущности, находящейся в источнике данных или data container, так и атрибутом связанной сущности; переход по графу объектов обозначается точкой. Например:<columns> <column id="date" property="date"/> <column id="customer" property="customer"/> <column id="customerName" property="customer.name"/> <column id="customerCountry" property="customer.address.country"/> </columns>
-
caption
- необязательный атрибут, содержит заголовок колонки. Если не задан, будет отображено локализованное название атрибута сущности.
-
expandRatio
- необязательный атрибут, устанавливает соотношение, с которым столбец расширяется. По умолчанию все колонки расширяются равномерно (словно все колонки имеютexpandRatio = 1
). Если хотя бы одной колонке установлено иное значение, все неявные значения удаляются и учитываются только проставленные.
-
collapsible
- необязательный атрибут, определяющий, может ли пользователь управлять отображением колонок с помощью меню (sidebar menu) в правой верхней частиDataGrid
. По умолчанию имеет значениеtrue
.
-
collapsed
- необязательный атрибут, при указанииtrue
колонка будет изначально скрыта. По умолчанию имеет значениеfalse
.
-
collapsingToggleCaption
- необязательный атрибут, задает имя колонки в меню в правой верхней частиDataGrid
. По умолчанию имеет значениеnull
, и в этом случае берется значение из заголовка колонки, доступного из свойстваcaption
.
-
resizable
- необязательный атрибут, определяет, может ли пользователь изменять размер колонки.
-
sortable
- необязательный атрибут, позволяющий запретить сортировку колонки. Вступает в действие, если атрибутsortable
всегоDataGrid
установлен вtrue
(что имеет место по умолчанию). -
width
- необязательный атрибут, отвечает за изначальную ширину колонки. Может принимать только числовые значения в пикселах.
-
minimumWidth
- необязательный атрибут, отвечает за минимальную ширину колонки. Может принимать только числовые значения в пикселах.
-
maximumWidth
- необязательный атрибут, отвечает за максимальную ширину колонки. Может принимать только числовые значения в пикселах.
Элемент
column
может содержать вложенный элемент formatter для представления значения атрибута в виде, отличном от стандартного для данного DataType:<column id="date" property="date"> <formatter class="com.haulmont.cuba.gui.components.formatters.DateFormatter" format="yyyy-MM-dd HH:mm:ss" useUserTimezone="true"/> </column>
-
-
actions
- необязательный элемент для описания действий, связанных сDataGrid
. Кроме описания произвольных действий, поддерживаются следующие стандартные действия, определяемые перечислениемListActionType
: create, edit, remove, refresh, add, exclude.
-
rowsCount
- необязательный элемент, создающий дляDataGrid
компонентRowsCount
, который позволяет загружать вDataGrid
данные постранично. Размер страницы задается путем ограничения количества записей в data loader’е методомCollectionLoader.setMaxResults()
в контроллере экрана. Также можно управлять количеством записей, используя универсальный компонентFilter
, связанный с источником данныхDataGrid
.Компонент
RowsCount
может также отобразить общее число записей, возвращаемых текущим запросом в источнике данных, без извлечения этих записей. По клику пользователя на знак "?" вызываетсяcom.haulmont.cuba.core.global.DataManager#getCount
, что приводит к выполнению в БД запроса с такими же, как у текущего запроса, условиями, но с агрегатной функциейCOUNT(*)
вместо результатов. Полученное число отображается вместо знака "?".Атрибут
autoLoad
компонентаRowsCount
, установленный в значениеtrue
, позволяет автоматически загружать общее число записей. Его можно установить в XML-дескрипторе:<rowsCount autoLoad="true"/>
Также включить или отключить автоматическую загрузку количества записей можно с помощью API в контроллере экрана:
boolean autoLoadEnabled = rowsCount.getAutoLoad(); rowsCount.setAutoLoad(false);
Атрибуты dataGrid
-
Атрибут
aggregatable
включает режим агрегации строк вDataGrid
. Поддерживаются следующие операции:-
SUM
− сумма -
AVG
− среднее значение -
COUNT
− количество -
MIN
− минимальное значение -
MAX
− максимальное значение
Для агрегируемых колонок необходимо указать элемент
aggregation
с атрибутомtype
, задающим функцию агрегации. По умолчанию в агрегируемых колонках поддерживаются только числовые типы данных, такие какInteger
,Double
,Long
иBigDecimal
. Агрегированные значения столбцов выводятся в дополнительной строке вверхуDataGrid
. Агрегирование в компонентеDataGrid
функционирует также, как и в компоненте Table. Это означает, что вы можете использовать strategyClass, valueDescription и formatter для агрегации.Пример описания
DataGrid
с агрегацией:<dataGrid id="ordersDataGrid" dataContainer="ordersDc" aggregationPosition="BOTTOM" aggregatable="true"> <columns> <column id="customerGrade" property="customer.grade"> <aggregation strategyClass="com.company.sample.CustomerGradeAggregation" valueDescription="msg://customerGradeAggregationDesc"/> </column> <column id="amount" property="amount"> <aggregation type="SUM"> <formatter class="com.company.sample.MyFormatter"/> </aggregation> </column> ... </columns> ... </dataGrid>
-
-
Атрибут
aggregationPosition
позволяет задать положение строки агрегации:TOP
илиBOTTOM
. По умолчанию используетсяTOP
.
-
columnResizeMode
- устанавливает режим изменения размера колонок пользователем. Поддерживаются следующие режимы (по умолчанию ANIMATED):-
ANIMATED
- размер колонки меняется сразу вслед за курсором. -
SIMPLE
- размер колонки меняется только после того, как курсор будет отпущен.
Изменение размера колонок можно отслеживать с помощью слушателя
ColumnResizeListener
. Источник события изменения размера можно отследить с помощью метода isUserOriginated(). -
-
columnsCollapsingAllowed
- разрешает или запрещает пользователю скрывать колонки с помощью меню (sidebar menu) в правой части шапкиDataGrid
. Существуют дополнительные пункты меню:-
Select all
− показать все колонки; -
Deselect all
− спрятать все колонки.Флажками в меню отмечаются отображаемые в данный момент колонки. В момент установки перезаписывает значение
collapsed
каждой отдельной колонки. Установка значения вfalse
не позволяет атрибутуcollapsed
отдельной колонки принять значениеtrue
.Скрытие и отображение колонок можно отслеживать с помощью слушателя
ColumnCollapsingChangeListener
. Источник события можно отследить с помощью метода isUserOriginated().
-
-
contextMenuEnabled
- включает или выключает контекстное меню вDataGrid
. По умолчанию имеет значениеtrue
.Щелчки правой кнопкой мыши по области компонента
DataGrid
можно отслеживать с помощью слушателяContextClickListener
.
-
editorBuffered
- включает буферизацию в режиме внутристрочного редактирования. По умолчанию буферизация разрешена (true
).
-
editorCancelCaption
- устанавливает заголовок кнопки отмены в режиме редактированияDataGrid
.
-
editorCrossFieldValidate
- включает перекрестную проверку полей во встроенном редакторе. По умолчанию имеет значениеtrue
.
-
editorEnabled
- включает отображение UI для внутристрочного редактирования ячеек. ЕслиdataGrid
привязан к источнику данных с типом KeyValueCollectionContainer, предполагается, что он используется только для чтения, и использование атрибутаeditorEnabled
в этом случае бессмысленно.
-
editorSaveCaption
- устанавливает заголовок кнопки сохранения изменений в режиме редактированияDataGrid
.
-
frozenColumnCount
- устанавливает количество фиксированных колонок вDataGrid
. Значение0
означает, что фиксированных колонок не будет, кроме встроенной колонки с чекбоксами для множественного выбора, если она используется. Значение-1
означает, что фиксированных колонок не будет вообще.
-
headerVisible
- определяет видимость заголовкаDataGrid
. По умолчанию имеет значениеtrue
.
-
htmlSanitizerEnabled
- разрешает или запрещает санитизацию HTML. КомпонентDataGrid
имеет несколько провайдеров, которые могут отображать HTML:-
HtmlRenderer
-
RowDescriptionProvider с режимом
ContentMode.HTML
-
DescriptionProvider с режимом
ContentMode.HTML
Результат выполнения этих провайдеров будет санитизирован, если для компонента
DataGrid
атрибутhtmlSanitizerEnabled
установлен в значениеtrue
.protected static final String UNSAFE_HTML = "<i>Jackdaws </i><u>love</u> <font size=\"javascript:alert(1)\" " + "color=\"moccasin\">my</font> " + "<font size=\"7\">big</font> <sup>sphinx</sup> " + "<font face=\"Verdana\">of</font> <span style=\"background-color: " + "red;\">quartz</span><svg/onload=alert(\"XSS\")>"; @Inject private DataGrid<Customer> customersDataGrid; @Inject private DataGrid<Customer> customersDataGrid2; @Inject private DataGrid<Customer> customersDataGrid3; @Subscribe public void onInit(InitEvent event) { customersDataGrid.setHtmlSanitizerEnabled(true); customersDataGrid.getColumn("name") .setRenderer(customersDataGrid.createRenderer(DataGrid.HtmlRenderer.class)); customersDataGrid2.setHtmlSanitizerEnabled(true); customersDataGrid2.setRowDescriptionProvider(customer -> UNSAFE_HTML, ContentMode.HTML); customersDataGrid3.setHtmlSanitizerEnabled(true); customersDataGrid3.getColumn("name").setDescriptionProvider(customer -> UNSAFE_HTML, ContentMode.HTML); }
Значение атрибута
htmlSanitizerEnabled
имеет приоритет над значением глобального свойства cuba.web.htmlSanitizerEnabled.Если вы хотите использовать
HtmlRenderer
с пользовательскимpresentationProvider
, результирующее значение не будет санитизировано по умолчанию. Если вам нужно санитизировать значение, вы должны это сделать самостоятельно:protected static final String UNSAFE_HTML = "<i>Jackdaws </i><u>love</u> <font size=\"javascript:alert(1)\" " + "color=\"moccasin\">my</font> " + "<font size=\"7\">big</font> <sup>sphinx</sup> " + "<font face=\"Verdana\">of</font> <span style=\"background-color: " + "red;\">quartz</span><svg/onload=alert(\"XSS\")>"; @Inject private DataGrid<Customer> customersDataGrid; @Inject private HtmlSanitizer htmlSanitizer; @Subscribe public void onInit(InitEvent event) { customersDataGrid.getColumn("name") .setRenderer(customersDataGrid.createRenderer(DataGrid.HtmlRenderer.class), (Function<String, String>) nameValue -> htmlSanitizer.sanitize(UNSAFE_HTML)); }
-
-
reorderingAllowed
- разрешает или запрещает пользователю менять местами колонки, перетаскивая их с помощью мыши. По умолчанию имеет значениеtrue
.Изменение расположения колонок можно отслеживать с помощью слушателя
ColumnReorderListener
. Источник события изменения порядка колонок можно отследить с помощью метода isUserOriginated().
-
selectionMode
- определяет режим выделения строк. Поддерживаются следующие режимы:-
SINGLE
- единичный выбор строки. -
MULTI
- множественный выбор строк как в таблице. -
MULTI_CHECK
- множественный выбор строк с использованием встроенной колонки с чекбоксами. -
NONE
- выбор строк отключен.Выделение строк можно отслеживать с помощью слушателя
SelectionListener
. Источник события выделения можно отследить с помощью метода isUserOriginated().
-
-
sortable
- разрешает или запрещает сортировку вDataGrid
. По умолчанию имеет значениеtrue
. Если сортировка разрешена, то при нажатии на название колонки справа от названия появляется соответствующий значок. Сортировку некоторой отдельной колонки можно запретить с помощью атрибутаsortable
этой колонки.События сортировки
DataGrid
можно отслеживать с помощью слушателяSortListener
. Источник события сортировки можно отследить с помощью метода isUserOriginated().
-
textSelectionEnabled
- разрешает или запрещает выделение текста в ячейкахDataGrid
. По умолчанию имеет значениеfalse
.
Методы интерфейса DataGrid
-
getColumns()
- возвращает текущий набор колонокDataGrid
в порядке их текущего отображения. -
getSelected()
,getSingleSelected()
- возвращают экземпляры сущностей, соответствующие выделенным в таблице строкам. Коллекцию можно получить вызовом методаgetSelected()
. Если ничего не выбрано, возвращается пустой набор. Если установленSelectionMode.SINGLE
, удобно пользоваться методомgetSingleSelected()
, возвращающим одну выбранную сущность илиnull
, если ничего не выбрано. -
getVisibleColumns()
- возвращет набор видимых колонокDataGrid
в порядке их текущего отображения.
-
scrollTo()
- позволяет программно прокрутитьDataGrid
до нужной записи. Метод принимает экземпляр сущности, определяющий нужную строку вDataGrid
. Перегруженный метод, помимо сущности, принимаетScrollDestination
, имеющий следующие возможные значения:-
ANY
- прокрутить как можно меньше, чтобы показать нужную запись. -
START
- прокрутить так, чтобы нужная запись оказалась в начале видимой областиDataGrid
. -
MIDDLE
- прокрутить так, чтобы нужная запись оказалась в центре видимой областиDataGrid
. -
END
- прокрутить так, чтобы нужная запись оказалась в конце видимой областиDataGrid
.
-
-
scrollToStart()
andscrollToEnd()
- позволяют прокрутитьDataGrid
в начало и конец соответственно.
-
addCellStyleProvider()
- позволяет добавить стиль отображения ячеекDataGrid
.
-
addRowStyleProvider()
- позволяет добавить стиль отображения строкDataGrid
.
-
setEnterPressAction()
- позволяет задать действие, выполняемое при нажатии клавиши Enter. Если такое действие не задано, таблица пытается найти среди своих действий подходящее в следующем порядке:-
действие, назначенное методом
setItemClickAction()
. -
действие, назначенное на клавишу Enter посредством свойства
shortcut
. -
действие с именем
edit
. -
действие с именем
view
.
Если такое действие найдено и имеет свойство
enabled = true
, оно выполняется. -
-
setItemClickAction()
- позволяет задать действие, выполняемое при двойном клике на строке таблицы. Если такое действие не задано, при двойном клике таблица пытается найти среди своих действий подходящее в следующем порядке:-
действие, назначенное на клавишу Enter посредством свойства
shortcut
. -
действие с именем
edit
. -
действие с именем
view
.
Если такое действие найдено и имеет свойство
enabled = true
, оно выполняется.События клика по элементу
DataGrid
можно отслеживать с помощью слушателяItemClickListener
. -
-
sort()
- сортирует данные в переданной колонке в направлении, заданном одним из двух доступных значений перечисленияSortDirection
:-
ASCENDING
- сортировка по возрастанию (например, A-Z, 1..9). -
DESCENDING
- сортировка по убыванию (например, Z-A, 9..1).
-
-
Метод
getAggregationResults()
возвращает мэп с результатами агрегации, где ключи в мэп − идентификаторы столбцовDataGrid
, а значения − значения агрегации.
Использование всплывающих подсказок
-
setDescriptionProvider()
- используется для генерации всплывающих подсказок для отдельных колонокDataGrid
. Строка описания может содержать HTML-разметку.@Inject private DataGrid<Customer> customersDataGrid; @Subscribe protected void onInit(InitEvent event) { customersDataGrid.getColumnNN("age").setDescriptionProvider(customer -> getPropertyCaption(customer, "age") + customer.getAge(), ContentMode.HTML); customersDataGrid.getColumnNN("active").setDescriptionProvider(customer -> getPropertyCaption(customer, "active") + getMessage(customer.getActive() ? "trueString" : "falseString"), ContentMode.HTML); customersDataGrid.getColumnNN("grade").setDescriptionProvider(customer -> getPropertyCaption(customer, "grade") + messages.getMessage(customer.getGrade()), ContentMode.HTML); }
-
setRowDescriptionProvider()
- используется для генерации всплывающих подсказок для строкDataGrid
. Если подсказки для колонок также установлены, подсказка, сгенерированная для строки, будет использована только для тех ячеек, для которых не задана подсказка колонки.customersDataGrid.setRowDescriptionProvider(Instance::getInstanceName);
Использование интерфейса DetailsGenerator
Интерфейс DetailsGenerator
позволяет задать свой компонент для отображения информации о выбранной строке DataGrid
с помощью метода setDetailsGenerator()
:
@Inject
private DataGrid<Order> ordersDataGrid;
@Inject
private UiComponents uiComponents;
@Install(to = "ordersDataGrid", subject = "detailsGenerator")
protected Component ordersDataGridDetailsGenerator(Order order) {
VBoxLayout mainLayout = uiComponents.create(VBoxLayout.NAME);
mainLayout.setWidth("100%");
mainLayout.setMargin(true);
HBoxLayout headerBox = uiComponents.create(HBoxLayout.NAME);
headerBox.setWidth("100%");
Label infoLabel = uiComponents.create(Label.NAME);
infoLabel.setHtmlEnabled(true);
infoLabel.setStyleName("h1");
infoLabel.setValue("Order info:");
Component closeButton = createCloseButton(order);
headerBox.add(infoLabel);
headerBox.add(closeButton);
headerBox.expand(infoLabel);
Component content = getContent(order);
mainLayout.add(headerBox);
mainLayout.add(content);
mainLayout.expand(content);
return mainLayout;
}
private Component createCloseButton(Order entity) {
Button closeButton = uiComponents.create(Button.class);
// ... (1)
return closeButton;
}
private Component getContent(Order entity) {
Label<String> content = uiComponents.create(Label.TYPE_STRING);
content.setHtmlEnabled(true);
StringBuilder sb = new StringBuilder();
// ... (2)
content.setValue(sb.toString());
return content;
}
1 | – Смотрите код метода createCloseButton целиком в классе DataGridDetailsGeneratorSample. |
2 | – Смотрите код метода getContent целиком в классе DataGridDetailsGeneratorSample. |
Результат:
Использование режима внутристрочного редактирования
У компонента DataGrid
есть API, позволяющий напрямую редактировать записи в ячейках. Во время редактирования ячейки будет отображён UI с кнопками для сохранения и отмены изменений.
Методы API встроенного редактора:
-
getEditedItem()
- возвращает редактируемую запись. -
isEditorActive()
- возвращаетtrue
, если в момент вызова редактируется какая-либо запись.
-
editItem(Object itemId)
(устаревший) - открывает интерфейс внутристрочного редактора для идентификатора указанной записи. Пролистывает таблицу до нужной записи, если в момент вызова она не была видна на экране.
-
edit(Entity item)
- открывает интерфейс внутристрочного редактора для указанной записи. Пролистывает таблицу до нужной записи, если в момент вызова она не была видна на экране.
Встроенный редактор DataGrid
может учитывать ограничения сущностей (перекрестная проверка полей). Если есть ошибки валидации, DataGrid
покажет сообщение об ошибке. Чтобы включить/отключить проверку или получить текущее состояние, используйте следующие методы:
-
setEditorCrossFieldValidate(boolean validate)
- включает или отключает перекрестную проверку полей во встроенном редакторе. По умолчанию имеет значениеtrue
. -
isEditorCrossFieldValidate()
- возвращает значениеtrue
, если для встроенного редактора включена перекрестная проверка полей.
Вы также можете добавить к встроенному редактору или удалить слушатели, использовав следующие методы:
-
addEditorOpenListener()
,removeEditorOpenListener()
- слушатель открытия встроенного редактораDataGrid
.Данный слушатель обрабатывает событие открытия встроенного редактора
DataGrid
по двойному щелчку и позволяет получить доступ к полям редактируемой строки. Это даёт возможность обновлять значения в отдельных полях в зависимости от изменения значений в других полях, не закрывая встроенный редактор.Например:
customersTable.addEditorOpenListener(editorOpenEvent -> { Map<String, Field> fieldMap = editorOpenEvent.getFields(); Field active = fieldMap.get("active"); Field grade = fieldMap.get("grade"); ValueChangeListener listener = e -> active.setValue(true); grade.addValueChangeListener(listener); });
-
addEditorCloseListener()
,removeEditorCloseListener()
- слушатель закрытия встроенного редактораDataGrid
.
-
addEditorPreCommitListener()
,removeEditorPreCommitListener()
- слушатель редактораDataGrid
, срабатывающий в процессе коммита изменений.
-
addEditorPostCommitListener()
,removeEditorPostCommitListener()
- слушатель, срабатывающий на финальной стадии коммита изменений.
Коммит изменений сохраняет их в источнике данных. Логику сохранения изменений в базу данных необходимо задать отдельно.
Само поле редактирования также может быть изменено с помощью класса EditorFieldGenerationContext
. Используйте метод setEditFieldGenerator()
для определённой колонки таблицы, чтобы указать компонент для отображения в режиме редактирования этой колонки:
@Inject
private DataGrid<Order> ordersDataGrid;
@Inject
private UiComponents uiComponents;
@Subscribe
protected void onInit(InitEvent event) {
ordersDataGrid.getColumnNN("amount").setEditFieldGenerator(orderEditorFieldGenerationContext -> {
LookupField<BigDecimal> lookupField = uiComponents.create(LookupField.NAME);
lookupField.setValueSource((ValueSource<BigDecimal>) orderEditorFieldGenerationContext
.getValueSourceProvider().getValueSource("amount"));
lookupField.setOptionsList(Arrays.asList(BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.TEN));
return lookupField;
});
}
Результат:
Использование интерфейса ColumnGenerator
DataGrid
имеет возможность добавлять генерируемые, или высчитываемые, колонки. Существует два пути создания таких колонок:
-
Декларативно, используя аннотацию
@Install
в контроллере экрана:@Inject private UiComponents uiComponents; @Install(to = "dataGrid.fullName", subject = "columnGenerator") protected Component fullNameColumnGenerator(DataGrid.ColumnGeneratorEvent<Customer> e) { Label<String> label = uiComponents.create(Label.TYPE_STRING); label.setValue(e.getItem().getFirstName() + " " + e.getItem().getLastName()); return label; }
ColumnGeneratorEvent
хранит информацию о сущности, которая отображается в текущей строкеDataGrid
, и идентификатор колонки. -
Программно с помощью следующих методов:
-
addGeneratedColumn(String columnId, ColumnGenerator generator)
-
addGeneratedColumn(String columnId, ColumnGenerator generator, int index)
ColumnGenerator
- это специальный интерфейс, который описывает генерируемую колонку:-
значение для каждой строки колонки,
-
тип значения - общий для всей колонки.
Например, для добавления генерируемой колонки, которая будет отображать логин пользователя в верхнем регистре, можно использовать следующий код:
@Subscribe protected void onInit(InitEvent event) { DataGrid.Column column = usersGrid.addGeneratedColumn("loginUpperCase", new DataGrid.ColumnGenerator<User, String>(){ @Override public String getValue(DataGrid.ColumnGeneratorEvent<User> event){ return event.getItem().getLogin().toUpperCase(); } @Override public Class<String> getType(){ return String.class; } }, 1); column.setCaption("Login Upper Case"); }
Результат:
По умолчанию, генерируемая колонка добавляется в конец таблицы. Управлять расположением генерируемых колонок можно либо вставляя колонку по индексу, либо предварительно добавив колонку в XML с
id
, который потом передавать в методaddGeneratedColumn
. -
Использование рендереров
Отображение данных в колонках может быть изменено с помощью параметризованных декларативных рендереров. Некоторые рендереры DataGrid
задаются специальными XML-элементами с параметрами, определенными в соответствующих атрибутах. Рендереры могут быть объявлены также и для не генерируемых колонок.
Список рендереров, поддерживаемых платформой:
-
ButtonRenderer
– рендерер, который использует строковое значение в качестве заголовка кнопки.ButtonRenderer
не может быть объявлен в XML-дескрипторе, так как в нем невозможно определить слушатель отслеживания кликов по кнопке. Studio сгенерирует код объявленияButtonRenderer
в методеinit()
контроллера экрана:@Inject private DataGrid<Customer> customersDataGrid; @Inject private Notifications notifications; @Subscribe public void onInit(InitEvent event) { DataGrid.ButtonRenderer<Customer> customersDataGridNameRenderer = customersDataGrid.createRenderer(DataGrid.ButtonRenderer.class); customersDataGridNameRenderer.setRendererClickListener(clickableButtonRendererClickEvent -> { notifications.create() .withType(Notifications.NotificationType.TRAY) .withCaption("ButtonRenderer") .withDescription("Column id: " + clickableButtonRendererClickEvent.getColumnId()) .show(); }); customersDataGrid.getColumn("name").setRenderer(customersDataGridNameRenderer); }
-
CheckBoxRenderer
– рендерер, который отображает булево значение в виде значков чек-бокса.Элемент
column
имеет вложенный элементcheckBoxRenderer
:<column property="checkBoxRenderer" id="checkBoxRendererColumn"> <checkBoxRenderer/> </column>
-
ClickableTextRenderer
– отображает простой текст в виде ссылки. Позволяет задать обработчик, который будет вызван после нажатия на ссылку.ClickableTextRenderer
не может быть объявлен в XML-дескрипторе, так как в нем невозможно определить слушатель отслеживания нажатий на ссылку. Studio сгенерирует код объявленияClickableTextRenderer
в методеinit()
контроллера экрана:@Inject private DataGrid<Customer> customersDataGrid; @Inject private Notifications notifications; @Subscribe public void onInit(InitEvent event) { DataGrid.ClickableTextRenderer<Customer> customersDataGridNameRenderer = customersDataGrid.createRenderer(DataGrid.ClickableTextRenderer.class); customersDataGridNameRenderer.setRendererClickListener(clickableTextRendererClickEvent -> { notifications.create() .withType(Notifications.NotificationType.TRAY) .withCaption("ClickableTextRenderer") .withDescription("Column id: " + clickableTextRendererClickEvent.getColumnId()) .show(); }); customersDataGrid.getColumn("name").setRenderer(customersDataGridNameRenderer); }
-
ComponentRenderer
– рендерер для компонентов UI.Элемент
column
имеет вложенный элементcomponentRenderer
:<column property="componentRenderer" id="componentRendererColumn"> <componentRenderer/> </column>
-
DateRenderer
– рендерер для отображения дат в заданном формате.Элемент
column
имеет вложенный элементdateRenderer
с необязательным атрибутомnullRepresentation
и обязательным строковым атрибутомformat
:<column property="dateRenderer" id="dateRendererColumn"> <dateRenderer nullRepresentation="null" format="yyyy-MM-dd HH:mm:ss"/> </column>
-
IconRenderer
– рендерер, который представляетCubaIcon
.Элемент
column
имеет вложенный элементiconRenderer
.Ниже приведен пример рендеринга строкового атрибута сущности в виде
CubaIcon
:<column id="iconOS" property="iconOS"> <iconRenderer/> </column>
@Install(to = "devicesTable.iconOS", subject = "columnGenerator") private Icons.Icon devicesTableIconOSColumnGenerator(DataGrid.ColumnGeneratorEvent<Device> event) { return CubaIcon.valueOf(event.getItem().getIconOS()); }
Результат:
-
ImageRenderer
– рендерер, который использует строковое значение в качестве пути до изображения.ImageRenderer
не может быть объявлен в XML-дескрипторе, так как в нем невозможно определить слушатель отслеживания нажатий на изображение. Studio сгенерирует код объявленияImageRenderer
в методеinit()
контроллера экрана:@Inject private DataGrid<TestEntity> testEntitiesDataGrid; @Inject private Notifications notifications; @Subscribe public void onInit(InitEvent event) { DataGrid.ImageRenderer<TestEntity> imageRenderer = testEntitiesDataGrid.createRenderer(DataGrid.ImageRenderer.class); imageRenderer.setRendererClickListener(imageRendererClickEvent -> notifications.create() .withType(Notifications.NotificationType.TRAY) .withCaption("ImageRenderer") .withDescription("Column id: " + imageRendererClickEvent.getColumnId()) .show()); testEntitiesDataGrid.getColumn("imageRendererColumn").setRenderer(imageRenderer); }
-
HtmlRenderer
– рендерер для отображения HTML-разметки.Элемент
column
имеет вложенный элементhtmlRenderer
с необязательным атрибутомnullRepresentation
:<column property="htmlRenderer" id="htmlRendererColumn"> <htmlRenderer nullRepresentation="null"/> </column>
-
LocalDateRenderer
– рендерер для отображения дат как значений типаLocalDate
.Элемент
column
имеет вложенный элементlocalDateRenderer
с необязательным атрибутомnullRepresentation
и обязательным строковым атрибутомformat
:<column property="localDateRenderer" id="localDateRendererColumn"> <localDateRenderer nullRepresentation="null" format="dd/MM/YYYY"/> </column>
-
LocalDateTimeRenderer
– рендерер для отображения дат как значений типаLocalDateTime
.Элемент
column
имеет вложенный элементlocalDateTimeRenderer
с необязательным атрибутомnullRepresentation
и обязательным строковым атрибутомformat
:<column property="localDateTimeRenderer" id="localDateTimeRendererColumn"> <localDateTimeRenderer nullRepresentation="null" format="dd/MM/YYYY HH:mm:ss"/> </column>
-
NumberRenderer
– рендерер для отображения чисел в заданном формате.Элемент
column
имеет вложенный элементnumberRenderer
с необязательным атрибутомnullRepresentation
и обязательным строковым атрибутомformat
:<column property="numberRenderer" id="numberRendererColumn"> <numberRenderer nullRepresentation="null" format="%f"/> </column>
-
ProgressBarRenderer
– рендерер, который отображаетdouble
-значения от 0 до 1 в виде компонентаProgressBar
.Элемент
column
имеет вложенный элементprogressBarRenderer
:<column property="progressBar" id="progressBarColumn"> <progressBarRenderer/> </column>
-
TextRenderer
– рендерер для отображения простого текста.Элемент
column
имеет вложенный элементtextRenderer
с необязательным атрибутомnullRepresentation
:<column property="textRenderer" id="textRendererColumn"> <textRenderer nullRepresentation="null"/> </column>
Интерфейс WebComponentRenderer
позволяет настроить отображение веб-компонентов различных типов в ячейках DataGrid
. Интерфейс реализован только для блока Web Module. Ниже приведён пример создания колонки для отображения компонента LookupField
:
@Inject
private DataGrid<User> usersGrid;
@Inject
private UiComponents uiComponents;
@Inject
private Configuration configuration;
@Inject
private Messages messages;
@Subscribe
protected void onInit(InitEvent event) {
Map<String, Locale> locales = configuration.getConfig(GlobalConfig.class).getAvailableLocales();
Map<String, String> options = new TreeMap<>();
for (Map.Entry<String, Locale> entry : locales.entrySet()) {
options.put(entry.getKey(), messages.getTools().localeToString(entry.getValue()));
}
DataGrid.Column column = usersGrid.addGeneratedColumn("language",
new DataGrid.ColumnGenerator<User, Component>() {
@Override
public Component getValue(DataGrid.ColumnGeneratorEvent<User> event) {
LookupField<String> component = uiComponents.create(LookupField.NAME);
component.setOptionsMap(options);
component.setWidth("100%");
User user = event.getItem();
component.setValue(user.getLanguage());
component.addValueChangeListener(e -> user.setLanguage(e.getValue()));
return component;
}
@Override
public Class<Component> getType() {
return Component.class;
}
});
column.setRenderer(new WebComponentRenderer());
}
Результат:
Когда тип поля не совпадает с типом данных, принимаемых рендерером, можно при создании рендерера создать функцию для конвертации между типами данных модели и представления. К примеру, чтобы отобразить булево значение в виде значка, можно использовать HtmlRenderer
, который умеет отображать HTML-разметку, и добавить логику, которая будет превращать булево значение в подходящую разметку для отображения значков.
@Inject
private DataGrid<User> usersGrid;
@Subscribe
protected void onInit(InitEvent event) {
DataGrid.Column<User> hasEmail = usersGrid.addGeneratedColumn("hasEmail", new DataGrid.ColumnGenerator<User, Boolean>() {
@Override
public Boolean getValue(DataGrid.ColumnGeneratorEvent<User> event) {
return StringUtils.isNotEmpty(event.getItem().getEmail());
}
@Override
public Class<Boolean> getType() {
return Boolean.class;
}
});
hasEmail.setCaption("Has Email");
hasEmail.setRenderer(
usersGrid.createRenderer(DataGrid.HtmlRenderer.class),
(Function<Boolean, String>) hasEmailValue -> {
return BooleanUtils.isTrue(hasEmailValue)
? FontAwesome.PLUS_SQUARE.getHtml()
: FontAwesome.MINUS_SQUARE.getHtml();
});
}
Результат:
Создавать рендереры можно тремя способами:
-
декларативно, используя специальные вложенные элементы у элемента
column
. -
через метод-фабрику интерфейса
DataGrid
, передавая в него интерфейс рендерера, для которого нужно создать имплементацию. Подходит для GUI и Web модулей. -
непосредственно создавая имплементацию рендерера для соответствующего модуля:
dataGrid.createRenderer(DataGrid.ImageRenderer.class) → new WebImageRenderer()
На данный момент этот способ реализован только для модуля Web.
Header и Footer
Интерфейсы HeaderRow
и FooterRow
предназначены для отображения ячеек заголовков и строк с итогами таблицы соответственно. Эти ячейки могут быть объединёнными для нескольких колонок.
Для создания и настройки заголовков и итогов используются следующие методы:
-
appendHeaderRow()
,appendFooterRow()
- добавляет новую строку внизу секции заголовков/итогов. -
prependHeaderRow()
,prependFooterRow()
- добавляет новую строку наверху секции заголовков/итогов. -
addHeaderRowAt()
,addFooterRowAt()
- вставляет новую строку на заданную позицию в секции. Текущая строка на этой позиции, а также все следующие ниже, сдвигаются вниз с увеличением их индекса на 1. -
removeHeaderRow()
,removeFooterRow()
- удаляет указанную строку в секции. -
getHeaderRowCount()
,getFooterRowCount()
- возвращает количество строк в секции. -
setDefaultHeaderRow()
- устанавливает заголовок таблицы по умолчанию. Интерфейс стандартного заголовка по умолчанию включает в себя элементы для сортировки колонок таблицы.
Интерфейсы HeaderCell
и FooterCell
позволяют управлять статическими ячейками:
-
setStyleName()
- устанавливает пользовательский стиль для данной ячейки. -
getCellType()
- возвращает тип содержимого данной ячейки. ПеречислениеDataGridStaticCellType
содержит 3 стандартных типа статических ячеек:-
TEXT
-
HTML
-
COMPONENT
-
-
getComponent()
,getHtml()
,getText()
- возвращает содержимое данной ячейки в зависимости от её типа.
Ниже приведён пример таблицы DataGrid
с заголовком, содержащим объединённые ячейки, и строкой итогов, в которой отображаются вычисляемые значения:
<dataGrid id="dataGrid" dataContainer="countryGrowthDs" width="100%">
<columns>
<column property="country"/>
<column property="year2017"/>
<column property="year2018"/>
</columns>
</dataGrid>
@Inject
private DataGrid<CountryGrowth> dataGrid;
@Inject
private UserSessionSource userSessionSource;
@Inject
private Messages messages;
@Inject
private CollectionContainer<CountryGrowth> countryGrowthsDc;
private DecimalFormat percentFormat;
@Subscribe
protected void onBeforeShow(BeforeShowEvent event) {
initPercentFormat();
initHeader();
initFooter();
initRenderers();
}
private DecimalFormat initPercentFormat() {
percentFormat = (DecimalFormat) NumberFormat.getPercentInstance(userSessionSource.getLocale());
percentFormat.setMultiplier(1);
percentFormat.setMaximumFractionDigits(2);
return percentFormat;
}
private void initRenderers() {
dataGrid.getColumnNN("year2017").setRenderer(new WebNumberRenderer(percentFormat));
dataGrid.getColumnNN("year2018").setRenderer(new WebNumberRenderer(percentFormat));
}
private void initHeader() {
DataGrid.HeaderRow headerRow = dataGrid.prependHeaderRow();
DataGrid.HeaderCell headerCell = headerRow.join("year2017", "year2018");
headerCell.setText("GDP growth");
headerCell.setStyleName("center-bold");
}
private void initFooter() {
DataGrid.FooterRow footerRow = dataGrid.appendFooterRow();
footerRow.getCell("country").setHtml("<strong>" + messages.getMainMessage("average") + "</strong>");
footerRow.getCell("year2017").setText(percentFormat.format(getAverage("year2017")));
footerRow.getCell("year2018").setText(percentFormat.format(getAverage("year2018")));
}
private double getAverage(String propertyId) {
double average = 0.0;
List<CountryGrowth> items = countryGrowthsDc.getItems();
for (CountryGrowth countryGrowth : items) {
Double value = countryGrowth.getValue(propertyId);
average += value != null ? value : 0.0;
}
return average / items.size();
}
Стили DataGrid
К компоненту DataGrid
можно применить заданные стили. Стиль задается в XML-дескрипторе с помощью атрибута stylename
.
<dataGrid id="dataGrid"
width="100%"
height="100%"
stylename="borderless"
dataContainer="customersDc">
</dataGrid>
Также стиль можно задать программно в контроллере экрана.
dataGrid.setStyleName("borderless");
Предопределенные стили:
-
borderless
- удаляет внешнюю рамку.
-
no-horizontal-lines
- удаляет горизонтальные строковые разделители.
-
no-vertical-lines
- удаляет вертикальные разделители столбцов.
-
no-stripes
- отключает чередование цветов строк таблицы.
Внешний вид компонента DataGrid
можно настроить с помощью переменных SCSS с префиксом $cuba-datagrid-*
. Эти переменные можно изменить в визуальном редакторе после расширения темы или создания новой темы.
- Атрибуты dataGrid
-
aggregatable - aggregationPosition - align - caption - captionAsHtml - colspan - columnResizeMode - columnsCollapsingAllowed - contextHelpText - contextHelpTextHtmlEnabled - contextMenuEnabled - css - dataContainer - description - descriptionAsHtml - editorBuffered - editorCancelCaption - editorCrossFieldValidate - editorEnabled - editorSaveCaption - emptyStateLinkMessage - emptyStateMessage - enable - box.expandRatio - frozenColumnCount - headerVisible - height - htmlSanitizerEnabled - icon - id - metaClass - reorderingAllowed - responsive - rowspan - selectionMode - settingsEnabled - sortable - stylename - tabIndex - textSelectionEnabled - visible - width
- Элементы dataGrid
-
actions - buttonsPanel - columns - rowsCount
- Атрибуты columns
- Атрибуты column
-
caption - collapsed - collapsible - collapsingToggleCaption - editable - expandRatio - id - maximumWidth - minimumWidth - property - resizable - sort - sortable - width
- Элементы column
-
aggregation - checkBoxRenderer - componentRenderer - dateRenderer - formatter - iconRenderer - htmlRenderer - localDateRenderer - localDateTimeRenderer - numberRenderer - progressBarRenderer - textRenderer
- Атрибуты aggregation
- API
-
addGeneratedColumn - applySettings - createRenderer - edit - getAggregationResults - saveSettings - getColumns - setDescriptionProvider - addCellStyleProvider - setConverter - setDetailsGenerator - setEditorCrossFieldValidate - setEmptyStateLinkClickHandler - setEnterPressAction - setItemClickAction - setRenderer - setRowDescriptionProvider - addRowStyleProvider - sort
- Слушатели dataGrid
-
ColumnCollapsingChangeListener - ColumnReorderListener - ColumnResizeListener - ContextClickListener - EditorCloseListener - EditorOpenListener - EditorPostCommitListener - EditorPreCommitListener - ItemClickListener - SelectionListener - SortListener
- Предопределенные стили
-
borderless - no-horizontal-lines - no-vertical-lines - no-stripes