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