4.5.2.1.6. DataGrid
DataGrid
, подобно компоненту Table, позволяет выводить информацию в виде таблицы, сортировать её, вызывать действия для выбранных строк, а также более эффективно управлять строками и колонками таблицы за счёт отложенной загрузки данных при прокрутке.
XML-имя компонента: dataGrid
.
Компонент реализован для блока Web Client.
Пример описания компонента в XML-дескрипторе экрана:
<dsContext>
<collectionDatasource id="ordersDs"
class="com.sample.sales.entity.Order"
view="orderWithCustomer">
<query>
select o from sales$Order o order by o.date
</query>
</collectionDatasource>
</dsContext>
<dataGrid id="ordersDataGrid"
datasource="ordersDs"
height="100%"
width="100%">
<columns>
<column id="date" property="date"/>
<column id="customerName" property="customer.name"/>
<column id="amount" property="amount"/>
</columns>
</dataGrid>
В данном примере атрибут id
- это идентификатор колонки, а атрибут property
содержит имя атрибута сущности, содержащейся в источнике данных, который следует использовать в качестве данных для колонки.
Элементы dataGrid:
-
columns
- обязательный элемент, определяет набор колонокDataGrid
. Каждая колонка описывается во вложенном элементеcolumn
со следующими атрибутами:-
id
- необязательный атрибут, содержит строковый идентификатор колонки. Если не задан, в качестве идентификатора колонки будет использоваться строковое значение атрибутаproperty
. В этом случае проставление атрибутаproperty
является обязательным, в противном случае будет брошено исключениеGuiDevelopmentException
. Атрибутid
по-прежнему является обязательным для колонки, создаваемой программно.
-
property
- необязательный атрибут, содержит название атрибута сущности, выводимого в колонке. Может быть как непосредственным атрибутом сущности, находящейся в источнике данных, так и атрибутом связанной сущности; переход по графу объектов обозначается точкой. Например:<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"> <formatter class="com.haulmont.cuba.gui.components.formatters.DateFormatter" format="yyyy-MM-dd HH:mm:ss"/> </column>
-
-
actions
- необязательный элемент для описания действий, связанных сDataGrid
. Кроме описания произвольных действий, поддерживаются следующие стандартные действия, определяемые перечислениемListActionType
: create, edit, remove, refresh, add, exclude.
-
rowsCount
- необязательный элемент, создающий дляDataGrid
компонентRowsCount
, который позволяет загружать вDataGrid
данные постранично. Размер страницы задается путем ограничения количества записей в источнике данных методомCollectionDatasource.setMaxResults()
в контроллере экрана. Также можно управлять количеством записей. используя универсальный компонентFilter
, связанный с источником данныхDataGrid
.
Компонент RowsCount
может также отобразить общее число записей, возвращаемых текущим запросом в источнике данных, без извлечения этих записей. Для этого при щелчке пользователя на знаке "?" он вызывает метод AbstractCollectionDatasource.getCount()
, что приводит к выполнению в БД запроса с такими же, как у текущего запроса, условиями, но с агрегатной функцией COUNT(*)
вместо результатов. Полученное число отображается вместо знака "?".
Атрибуты dataGrid:
-
columnResizeMode
- устанавливает режим изменения размера колонок пользователем. Поддерживаются следующие режимы (по умолчанию ANIMATED):-
AMINATED
- размер колонки меняется сразу вслед за курсором. -
SIMPLE
- размер колонки меняется только после того как курсор будет отпущен.
-
-
columnsCollapsingAllowed
- разрешает или запрещает пользователю скрывать колонки с помощью меню (sidebar menu) в правой части шапкиDataGrid
. Флажками в меню отмечаются отображаемые в данный момент колонки. В момент установки перезаписывает значениеcollapsed
каждой отдельной колонки. Установка значения вfalse
не позволяет атрибутуcollapsed
отдельной колонки принять значениеtrue
.
-
contextMenuEnabled
- включает или выключает контекстное меню вDataGrid
. По умолчанию имеет значениеtrue
.
-
frozenColumnCount
- устанавливает количество фиксированных колонок вDataGrid
. Значение0
означает, что фиксированных колонок не будет, кроме встроенной колонки с чекбоксами для множественного выбора, если она используется. Значение-1
означает, что фиксированных колонок не будет вообще.
-
headerVisible
- определяет видимость заголовкаDataGrid
. По умолчанию имеет значениеtrue
.
-
reorderingAllowed
- разрешает или запрещает пользователю менять местами колонки, перетаскивая их с помощью мыши. По умолчанию имеет значениеtrue
.
-
responsive
- определяет, должен ли компонент реагировать на изменения размеров доступной области. Реакцию можно задать с помощью стилей.
-
selectionMode
- определяет режим выделения строк. Поддерживаются следующие режимы:-
SINGLE
- единичный выбор строки. -
MULTI
- множественный выбор строк как в таблице. -
MULTI_CHECK
- множественный выбор строк с использованием встроенной колонки с чекбоксами. -
NONE
- выбор строк отключен.
-
-
settingsEnabled
- определяет, нужно ли сохранять пользовательские настройки внешнего видаDataGrid
. По умолчанию имеет значениеtrue
.
-
sortable
- разрешает или запрещает сортировку вDataGrid
. По умолчанию имеет значениеtrue
. Если сортировка разрешена, то при нажатии на название колонки справа от названия появляется соответствующий значок. Сортировку некоторой отдельной колонки можно запретить с помощью атрибутаsortable
этой колонки.
-
textSelectionEnabled
- разрешает или запрещает выделение текста в ячейкахDataGrid
. По умолчанию имеет значениеfalse
.
Методы интерфейса DataGrid:
-
getColumns()
- возвращет текущий набор колонокDataGrid
в порядке их текущего отображения. -
getSelected()
,getSingleSelected()
- возвращают экземпляры сущностей, соответствующие выделенным в таблице строкам. Коллекцию можно получить вызовом методаgetSelected()
. Если ничего не выбрано, возвращается пустой набор. Если установленSelectionMode.NONE
, удобно пользоваться методомgetSingleSelected()
, возвращающим одну выбранную сущность илиnull
, если ничего не выбрано. -
getVisibleColumns()
- возвращет набор видимых колонокDataGrid
в порядке их текущего отображения. -
scrollTo()
- позволяет программно прокрутитьDataGrid
до нужной записи. Метод принимает экземпляр сущности, определяющий нужную строку вDataGrid
. Перегруженный метод, помимо сущности, принимаетScrollDestination
, имеющий следующие возможные значения:-
ANY
- прокрутить как можно меньше, чтобы показать нужную запись. -
START
- прокрутить так, чтобы нужная запись оказалась в начале видимой областиDataGrid
. -
MIDDLE
- прокрутить так, чтобы нужная запись оказалась в центре видимой областиDataGrid
. -
END
- прокрутить так, чтобы нужная запись оказалась в конце видимой областиDataGrid
.
-
-
scrollToStart()
andscrollToEnd()
- позволяют прокрутитьDataGrid
в начало и конец соотвественно. -
setCellStyleProvider()
- позволяет задать стиль отображения ячеекDataGrid
. -
setRowStyleProvider()
- позволяет задать стиль отображения строкDataGrid
. -
setEnterPressAction()
- позволяет задать действие, выполняемое при нажатии клавиши Enter. Если такое действие не задано, таблица пытается найти среди своих действий подходящее в следующем порядке:-
действие, назначенное методом
setItemClickAction()
. -
действие, назначенное на клавишу Enter посредством свойства
shortcut
. -
действие с именем
edit
. -
действие с именем
view
.
Если такое действие найдено и имеет свойство
enabled = true
, оно выполняется. -
-
setItemClickAction()
- позволяет задать действие, выполняемое при двойном клике на строке таблицы. Если такое действие не задано, при двойном клике таблица пытается найти среди своих действий подходящее в следующем порядке:-
действие, назначенное на клавишу Enter посредством свойства
shortcut
. -
действие с именем
edit
. -
действие с именем
view
.
Если такое действие найдено и имеет свойство
enabled = true
, оно выполняется. -
-
sort()
- сортирует данные в переданной колонке в направлении, заданном одним из двух доступных значений перечисленияSortDirection
:-
ASCENDING
- сортировка по возрастанию (например, A-Z, 1..9). -
DESCENDING
- сортировка по убыванию (например, Z-A, 9..1).
-
-
setCellDescriptionProvider()
- принимает экземплярCellDescriptionProvider
, который будет использоваться для генерации всплывающих подсказок для отдельных ячеек DataGrid. Строка описания может содержать HTML-разметку.customersDataGrid.setRowDescriptionProvider(Instance::getInstanceName);
-
setRowDescriptionProvider()
- принимает экземплярRowDescriptionProvider
, который будет использоваться для генерации всплывающих подсказок для строк DataGrid. ЕслиCellDescriptionProvider
также установлен, подсказка, сгенерированнаяRowDescriptionProvider
, будет использована только для тех ячеек, для которых не задана подсказка ячейки.customersDataGrid.setCellDescriptionProvider((entity,columnId)->{ if ("name".equals(columnId)||"lastName".equals(columnId)){ return null; } String description="<strong>"+ messages.getTools().getPropertyCaption(entity.getMetaClass(),columnId)+ ": </strong>"; if ("grade".equals(columnId)){ description += messages.getMessage(entity.getGrade()); } else if ("active".equals(columnId)){ description += getMessage(entity.getActive() ? "trueString":"falseString"); } else { description += entity.getValue(columnId); } return description; });
Использование интерфейса ColumnGenerator:
DataGrd
имеет возможность добавлять генерируемые, или высчитываемые, колонки. Для этого существует два метода:
-
addGeneratedColumn(String columnId, ColumnGenerator generator)
-
addGeneratedColumn(String columnId, ColumnGenerator generator, int index)
ColumnGenerator
- это специальный интерфейс, который описывает генерируемую колонку:
-
значение для каждой строки колонки,
-
тип значения - общий для всей колонки.
Например, для добавления генерируемой колонки, которая будет отображать логин пользователя в верхнем регистре, можно использовать следующий код:
@Override
public void init(Map<String, Object> params){
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");
}
Результат:
ColumnGeneratorEvent
, который передается в getValue
, хранит информацио о сущности, которая отображется в текущей строке DataGrid
, и propertyId
колонки.
По умолчанию, генерируемая колонка добавляется в конец таблицы. Управлять расположением генерируемых колонок можно либо вставляя колонку по индексу, либо предварительно добавив колонку в XML с id
, который потом передавать в метод addGeneratedColumn
.
Отображение данных в колонках может быть изменено с помощью рендереров. Предположим, что нам необходимо показывать изображение в строке. Тогда текстовое значение пути до изображения можно отобразить в виде изображения с помощью ImageRenderer
:
@Override
public void init(Map<String, Object> params){
DataGrid.Column avatar = usersGrid.addGeneratedColumn("userAvatar", new DataGrid.ColumnGenerator<User, String>() {
@Override
public String getValue(DataGrid.ColumnGeneratorEvent<User> event) {
return "icons/user.png";
}
@Override
public Class<String> getType() {
return String.class;
}
}, 0);
avatar.setCaption("Avatar");
avatar.setRenderer(usersGrid.createRenderer(DataGrid.ImageRenderer.class));
}
Результат:
Когда тип поля не совпадает с типом данных, принимаемых рендерером, удобно пользоваться конвертерами, которые обеспечивают конвертацию между типами данных модели и представления. К примеру, чтобы отобразить булево значение в виде пиктограммы, можно использовать HtmlRenderer
, который умеет отображать HTML-разметку, и конвертер, который будет превращать булево значение в подходящую разметку для отображения иконок.
@Override
public void init(Map<String, Object> params){
DataGrid.Column 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));
hasEmail.setConverter(new DataGrid.Converter<String, Boolean>() {
@Override
public Boolean convertToModel(String value, Class<? extends Boolean> targetType, Locale locale) {
return null;
}
@Override
public String convertToPresentation(Boolean value, Class<? extends String> targetType, Locale locale) {
return BooleanUtils.isTrue(value)
? FontAwesome.CHECK_SQUARE_O.getHtml()
: FontAwesome.SQUARE_O.getHtml();
}
@Override
public Class<Boolean> getModelType() {
return Boolean.class;
}
@Override
public Class<String> getPresentationType() {
return String.class;
}
});
}
Результат:
Создавать рендереры можно двумя способами:
-
через метод-фабрику интерфейса
DataGrid
, передавая в него интерфейс рендерера, для которого нужно создать имплементацию. Подходит для GUI и Web модулей. -
непосредственно создавая имплементацию рендерера для соответствующего модуля:
dataGrid.createRenderer(DataGrid.ImageRenderer.class) → new WebImageRenderer()
На данный момент этот способ реализован только для модуля Web.
Список рендереров, реализованных в платформе:
-
TextRenderer
- рендерер для отображения простого текста. -
HtmlRenderer
- рендерер для отображения HTML-разметки. -
ProgressBarRenderer
- рендерер, который отображаетdouble
-значения в виде компонентаProgressBar
. -
DateRenderer
- рендерер для отображения дат в заданном формате. -
NumberRenderer
- рендерер для отображения чисел в заданном формате. -
ButtonRenderer
- рендерер, который использует строковое значение в качестве заголовка кнопки. -
ImageRenderer
- рендерер, который использует строковое значение в качестве пути до изображения. -
CheckBoxRenderer
- рендерер, который отображает булево значение в виде иконок чек-бокса.
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"
datasource="countryGrowthDs"
width="100%">
<columns>
<column property="country"/>
<column property="year2014"/>
<column property="year2015"/>
</columns>
</dataGrid>
public class DataGridHeaderFooterFrame extends AbstractFrame {
@Inject
private DataGrid<CountryGrowth> dataGrid;
@Inject
private CollectionDatasource<CountryGrowth, UUID> countryGrowthDs;
@Inject
private UserSessionSource userSessionSource;
private DecimalFormat percentFormat;
@Override
public void init(Map<String, Object> params) {
countryGrowthDs.refresh();
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("year2014").setRenderer(new WebNumberRenderer(percentFormat));
dataGrid.getColumnNN("year2015").setRenderer(new WebNumberRenderer(percentFormat));
}
private void initHeader() {
HeaderRow headerRow = dataGrid.prependHeaderRow();
HeaderCell headerCell = headerRow.join("year2014", "year2015");
headerCell.setText("GDP growth");
headerCell.setStyleName("center-bold");
}
private void initFooter() {
FooterRow footerRow = dataGrid.appendFooterRow();
footerRow.getCell("country").setHtml("<strong>" + getMessage("average") + "</strong>");
footerRow.getCell("year2014").setText(percentFormat.format(getAverage("year2014")));
footerRow.getCell("year2015").setText(percentFormat.format(getAverage("year2015")));
}
private double getAverage(String propertyId) {
double average = 0.0;
Collection<CountryGrowth> items = countryGrowthDs.getItems();
for (CountryGrowth countryGrowth : items) {
Double value = countryGrowth.getValue(propertyId);
average += value != null ? value : 0.0;
}
return average / items.size();
}
}
- Атрибуты dataGrid
-
align - caption - colspan - columnResizeMode - columnsCollapsingAllowed - contextMenuEnabled - datasource - description - enable - frozenColumnCount - headerVisible - height - icon - id - reorderingAllowed - responsive - rowspan - selectionMode - settingsEnabled - sortable - stylename - textSelectionEnabled - visible - width
- Элементы dataGrid
-
actions - buttonsPanel - columns - rowsCount
- Атрибуты column
-
caption - collapsed - collapsible - collapsingToggleCaption - expandRatio - id - maximumWidth - minimumWidth - property - resizable - sortable - width
- Элементы column