5.5.2.1.39. Table
Компонент Table
позволяет выводить информацию в табличном виде, сортировать данные, управлять колонками и заголовками таблицы, вызывать действия для выбранных строк.
XML-имя компонента: table
Компонент реализован для блоков Web Client и Desktop Client.
Пример описания таблицы в XML-дескрипторе экрана:
<dsContext>
<collectionDatasource id="ordersDs"
class="com.sample.sales.entity.Order"
view="order-with-customer">
<query>
select o from sales$Order o order by o.date
</query>
</collectionDatasource>
</dsContext>
<layout>
<table id="ordersTable" width="300px">
<columns>
<column id="date"/>
<column id="customer.name"/>
<column id="amount"/>
</columns>
<rows datasource="ordersDs"/>
</table>
Здесь в элементе dsContext
определен источник данных collectionDatasource
, который выбирает сущности Order
с помощью JPQL запроса select o from sales$Order o order by o.date
. Для компонента table
в элементе rows
указывается используемый источник данных, а в элементе columns
- какие атрибуты сущности, содержащейся в источнике данных, использовать в качестве колонок.
Элементы table
:
-
rows
- обязательный элемент, в атрибутеdatasource
которого необходимо объявить используемый таблицей источник данных.Для строк можно настроить отображение заголовков - задать каждой строке свой значок в дополнительной колонке слева. Для этого в контроллере экрана необходимо реализовать интерфейс
ListComponent.IconProvider
и установить его таблице:@Inject private Table<Customer> table; @Override public void init(Map<String, Object> params) { table.setIconProvider(new ListComponent.IconProvider<Customer>() { @Nullable @Override public String getItemIcon(Customer entity) { CustomerGrade grade = entity.getGrade(); switch (grade) { case PREMIUM: return "icons/premium_grade.png"; case HIGH: return "icons/high_grade.png"; case MEDIUM: return "icons/medium_grade.png"; default: return null; } } }); }
-
columns
- обязательный элемент, определяет набор колонок таблицы.Каждая колонка описывается во вложенном элементе
column
со следующими атрибутами:-
id
− обязательный атрибут, содержит название атрибута сущности, выводимого в колонке. Может быть как непосредственным атрибутом сущности, находящейся в источнике данных, так и атрибутом связанной сущности - переход по графу объектов обозначается точкой. Например:<columns> <column id="date"/> <column id="customer"/> <column id="customer.name"/> <column id="customer.address.country"/> </columns>
-
collapsed
− необязательный атрибут, при указанииtrue
колонка будет изначально скрыта. Пользователь может управлять отображением колонок с помощью меню, доступного по кнопке в правой верхней части таблицы, если атрибутcolumnControlVisible
таблицы неfalse
. По умолчаниюcollapsed
имеет значениеfalse
.
-
width
− необязательный атрибут, отвечает за изначальную ширину колонки. Может принимать только числовые значения в пикселах.
-
align
- необязательный атрибут, устанавливает выравнивание текста в ячейках данной колонки. Возможные значения:LEFT
,RIGHT
,CENTER
. По умолчаниюLEFT
.
-
editable
− необязательный атрибут, разрешает/запрещает редактирование данной колонки в редактируемой таблице. Чтобы колонка была редактируемой, атрибут editable всей таблицы также должен быть установлен вtrue
. Динамическое изменение значения этого атрибута не поддерживается.
-
sortable
− необязательный атрибут, позволяющий запретить сортировку колонки. Вступает в действие, если атрибут sortable всей таблицы установлен вtrue
(что имеет место по умолчанию).
-
maxTextLength
- необязательный атрибут, позволяет ограничивать количество символов в ячейке. При этом если разница между фактическим и допустимым количеством символов не превышает порог в 10 символов, "лишние" символы не скрываются. Для просмотра полной записи надо кликнуть на ее видимую часть. Пример колонки с ограничением в 5 символов:
-
link
- установка атрибута вtrue
позволяет отобразить в ячейке таблицы ссылку на экран просмотра экземпляра сущности (поддерживается только для Web Client). Атрибутlink="true"
) может указываться и для колонок примитивных типов: в этом случае, при нажатии на ссылку будет открываться редактор основной сущности таблицы. Такой подход может применяться для упрощения навигации - пользователи смогут открывать редактор одним кликом по некоторому ключевому атрибуту.
-
linkScreen
- позволяет указать идентификатор экрана, который будет открыт по нажатию на ссылку, включенную свойствомlink
.
-
linkScreenOpenType
- задает режим открытия экрана (THIS_TAB
,NEW_TAB
илиDIALOG
).
-
linkInvoke
- позволяет заменить открытие окна на вызов метода контроллера.public void linkedMethod(Entity item, String columnId) { Customer customer = (Customer) item; showNotification(customer.getName()); }
-
необязательный атрибут
generator
содержит ссылку на метод в контроллере экрана, который создает визуальный компонент для отображения содержимого ячейки:<columns> <column id="name"/> <column id="imageFile" generator="generateImageFileCell"/> </columns>
public Component generateImageFileCell(Employee entity) { Embedded embedded = componentsFactory.createComponent(Embedded.class); embedded.setType(Embedded.Type.IMAGE); FileDescriptor userImageFile = entity.getImageFile(); FileDataProvider dataProvider = new FileDataProvider(userImageFile); embedded.setSource(userImageFile.getId() + "." + userImageFile.getExtension(), dataProvider); return embedded; }
Он может быть использован вместо передачи реализации
Table.ColumnGenerator
в метод addGeneratedColumn(). -
Элемент
column
может содержать вложенный элемент formatter для представления значения атрибута в виде, отличном от стандартного для данного Datatype:<column id="date"> <formatter class="com.haulmont.cuba.gui.components.formatters.DateFormatter" format="yyyy-MM-dd HH:mm:ss"/> </column>
-
-
rowsCount
− необязательный элемент, создающий для таблицы компонентRowsCount
, который позволяет загружать в таблицу данные постранично. Размер страницы задается путем ограничения количества записей в источнике данных методомCollectionDatasource.setMaxResults()
. Как правило, это делает связанный с источником данных таблицы компонент Filter, однако при отсутствии универсального фильтра можно вызвать этот метод и напрямую из контроллера экрана.Компонент
RowsCount
может также отобразить общее число записей, возвращаемых текущим запросом в источнике данных, без извлечения этих записей. Для этого при щелчке пользователя на знаке "?" он вызывает методAbstractCollectionDatasource.getCount()
, что приводит к выполнению в БД запроса с такими же, как у текущего запроса условиями, но с агрегатной функциейCOUNT(*)
вместо результатов. Полученное число отображается вместо знака "?".
-
actions
− необязательный элемент для описания действий, связанных с таблицей. Кроме описания произвольных действий, поддерживаются следующие стандартные действия, определяемые перечислениемListActionType
:create
,edit
,remove
,refresh
,add
,exclude
,excel
.
Атрибуты table
:
-
Атрибут
multiselect
позволяет задать режим множественного выделения строк в таблице. Еслиmultiselect
равенtrue
, то пользователь может выделить несколько строк с помощью клавиатуры или мыши, удерживая клавиши Ctrl или Shift. По умолчанию режим множественного выделения отключен.
-
Атрибут
sortable
разрешает или запрещает сортировку в таблице. По умолчанию имеет значениеtrue
. Если сортировка разрешена, то при нажатии на название колонки справа от названия появляется значок /. Сортировку некоторой отдельной колонки можно запретить с помощью атрибута sortable этой колонки.При включенной с помощью элемента
rowsCount
(см. выше) страничной загрузке таблицы сортировка производится разными способами в зависимости от того, умещаются ли все записи на одной странице. Если умещаются, то сортировка производится в памяти, без обращений к БД. Если же страниц больше одной, то сортировка производится на базе данных путем отправки нового запроса с соответствующимORDER BY
.Колонка таблицы может ссылаться на локальный атрибут или на связанную сущность. Например:
<table id="ordersTable"> <columns> <column id="customer.name"/> <!-- the 'name' attribute of the 'Customer' entity --> <column id="contract"/> <!-- the 'Contract' entity --> </columns> <rows datasource="ordersDs"/> </table>
В последнем случае, сортировка на базе данных производится по атрибутам, указанным в аннотации
@NamePattern
связанной сущности. Если у связанной сущности нет такой аннотации, то сортировка производится в памяти только в пределах текущей страницы.Если колонка таблицы ссылается на неперсистентный атрибут, то сортировка на базе данных производится по атрибутам, указанным в параметре
related()
аннотации@MetaProperty
. Если такой параметр не указан, то сортировка производится в памяти только в пределах текущей страницы.Если таблица соединена со вложенным источником данных, который содержит коллекцию связанных сущностей, то для того, чтобы таблицу можно было сортировать, атрибут-коллекция должен быть упорядоченного типа (
List
илиLinkedHashSet
). Если атрибут имеет типSet
, то атрибутsortable
не оказывает влияния и пользователи не смогут сортировать таблицу.
-
Атрибут
presentations
управляет механизмом представлений. Значение по умолчанию равноfalse
. Когда значение атрибута равноtrue
, то в верхнем правом углу таблицы появляется значок . Механизм представлений реализован только для блока Web Client.
-
Установка атрибута
columnControlVisible
вfalse
запрещает пользователю скрывать колонки с помощью меню, выпадающего при нажатия на кнопку в правой части шапки таблицы. Флажками в меню отмечаются отображаемые в данный момент колонки.
-
Установка атрибута
reorderingAllowed
вfalse
запрещает пользователю менять местами колонки, перетаскивая их с помощью мыши.
-
Установка атрибута
columnHeaderVisible
вfalse
скрывает заголовок таблицы.
-
При установленном в
false
атрибутеshowSelection
текущая строка не имеет выделения.
-
Атрибут
contextMenuEnabled
разрешает или запрещает показывать контекстное меню. По умолчанию атрибут имеет значениеtrue
. В контекстном меню отображаются действия таблицы (если они есть), и пункт Системная информация, содержащий информацию о выбранной сущности (если у пользователя есть разрешениеcuba.gui.showInfo
).
-
Если атрибуту
multiLineCells
таблицы присвоить значениеtrue
, то ячейки, содержащие текст с переносами строк, будут отображать его в несколько строк. В таком режиме в веб клиенте для правильной работы полосы прокрутки все строки текущей страницы таблицы будут загружены веб-браузером сразу, без ленивой загрузки видимой части таблицы. По умолчанию атрибут имеет значениеfalse
.
-
Атрибут
aggregatable
включает режим агрегации строк таблицы. Поддерживаются следующие операции:-
SUM
- сумма -
AVG
- среднее значение -
COUNT
- количество -
MIN
- минимальное значение -
MAX
- максимальное значение
Для агрегируемых колонок необходимо указать элемент
aggregation
с атрибутомtype
, задающим функцию агрегации. По умолчанию в агрегируемых колонках поддерживаются только числовые типы данных, такие какInteger, Double, Long
иBigDecimal
. Агрегированные значения столбцов выводятся в дополнительной строке вверху таблицы. Пример описания таблицы с агрегацией:<table id="itemsTable" aggregatable="true"> <columns> <column id="product"/> <column id="quantity"/> <column id="amount"> <aggregation type="SUM"/> </column> </columns> <rows datasource="itemsDs"/> </table>
Элемент
aggregation
может также содержать атрибутstrategyClass
, указывающий класс, реализующий интерфейсAggregationStrategy
interface (см. ниже пример установки стратегии агрегации программно).Для отображения агрегированного значения в виде, отличном от стандартного для данного Datatype, для него можно указать Formatter:
<column id="amount"> <aggregation type="SUM"> <formatter class="com.company.sample.MyFormatter"/> </aggregation> </column>
Атрибут
aggregationStyle
позволяет задать положение строки агрегации:TOP
илиBOTTOM
. По умолчанию используетсяTOP
.В дополнение к операциям, перечисленным выше, можно задать собственную стратегию агрегации путем создания класса, реализующего интерфейс
AggregationStrategy
, и передачи его методуsetAggregation()
классаTable.Column
в составе экземпляраAggregationInfo
. Например:public class TimeEntryAggregation implements AggregationStrategy<List<TimeEntry>, String> { @Override public String aggregate(Collection<List<TimeEntry>> propertyValues) { HoursAndMinutes total = new HoursAndMinutes(); for (List<TimeEntry> list : propertyValues) { for (TimeEntry timeEntry : list) { total.add(HoursAndMinutes.fromTimeEntry(timeEntry)); } } return StringFormatHelper.getTotalDayAggregationString(total); } @Override public Class<String> getResultClass() { return String.class; } }
AggregationInfo info = new AggregationInfo(); info.setPropertyPath(metaPropertyPath); info.setStrategy(new TimeEntryAggregation()); Table.Column column = weeklyReportsTable.getColumn(columnId); column.setAggregation(info);
-
-
Атрибут
editable
позволяет перевести таблицу в режим in-place редактирования ячеек. В этом режиме в колонках, имеющих атрибутeditable = true
, отображаются компоненты для редактирования значений атрибутов сущности, находящейся в источнике данных.Тип компонента для каждой редактируемой колонки выбирается автоматически на основании типа атрибута сущности. Например, для строковых и числовых атрибутов используется TextField, для
Date
- DateField, для перечислений - LookupField, для ссылок на другие сущности - PickerField.Для редактируемой колонки типа
Date
можно дополнительно указать атрибутыdateFormat
илиresolution
аналогично описанным для DateField.Для редактируемой колонки, отображающей связанную сущность, можно дополнительно указать атрибуты optionsDatasource и captionProperty. При указании
optionsDatasource
вместо PickerField используется компонент LookupField.Произвольно настроить отображение ячеек, в том числе для редактирования содержимого, можно с помощью метода
Table.addGeneratedColumn()
- см. ниже.
-
В веб-клиенте с темой, основанной на Halo, атрибут
stylename
позволяет применять к таблице предопределенные стилиTable
. Стили задаются в XML-дексрипторе или контроллере экрана с помощью атрибутаstylename
:<table id="table" stylename="no-stripes"> <columns> <column id="product"/> <column id="quantity"/> </columns> <rows datasource="itemsDs"/> </table>
Чтобы применить стиль программно, выберите одну из констант класса
HaloTheme
с префиксом компонентаTABLE_
:table.setStyleName(HaloTheme.TABLE_NO_STRIPES);
Стили компонента Table:
-
borderless
- удаляет внешнюю рамку таблицы.
-
compact
- уменьшает отступы внутри ячеек таблицы.
-
no-header
- скрывает заголовки таблицы.
-
no-horizontal-lines
- удаляет горизонтальные строковые разделители.
-
no-stripes
- отключает чередование цветов строк таблицы.
-
no-vertical-lines
- удаляет вертикальные разделители столбцов.
-
small
- уменьшает размер шрифта и отступы внутри ячеек таблицы.
-
Методы интерфейса Table
:
-
метод
addColumnCollapsedListener
() позволяет отслеживать видимость колонок таблицы с помощью интерфейса слушателяColumnCollapsedListener
.
-
getSelected()
,getSingleSelected()
- возвращают экземпляры сущностей, соответствующие выделенным в таблице строкам. Коллекцию можно получить вызовом методаgetSelected()
. Если ничего не выбрано, возвращается пустой набор. Еслиmultiselect
отключен, удобно пользоваться методомgetSingleSelected()
, возвращающим одну выбранную сущность илиnull
, если ничего не выбрано.
-
Метод
addGeneratedColumn()
позволяет задать собственное представление данных в колонке. Он принимает два параметра: идентификатор колонки и реализацию интерфейсаTable.ColumnGenerator
. Идентификатор может совпадать с одним из идентификаторов, указанных для колонок таблицы в XML-дескрипторе - в этом случае новая колонка вставляется вместо заданной в XML. Если идентификатор не совпадает ни с одной колонкой, создается новая справа.Метод
generateCell()
интерфейсаTable.ColumnGenerator
вызывается таблицей для каждой строки, и в него передается экземпляр сущности, отображаемой в данной строке. МетодgenerateCell()
должен вернуть визуальный компонент, который и будет отображаться в ячейке.Пример использования:
@Inject protected Table carsTable; @Inject protected ComponentsFactory componentsFactory; @Override public void init(Map<String, Object> params) { carsTable.addGeneratedColumn("colour", new Table.ColumnGenerator() { @Override public Component generateCell(Entity entity) { LookupPickerField field = componentsFactory.createComponent(LookupPickerField.NAME); field.setDatasource(carsTable.getItemDatasource(entity), "colour"); field.setOptionsDatasource(coloursDs); field.addLookupAction(); field.addOpenAction(); return field; } }); }
В данном случае в ячейках колонки
colour
таблицы отображается компонент LookupPickerField. Компонент должен сохранять свое значение в атрибутcolour
сущности, экземпляр которой отображается в данной строке. Для этого у таблицы методомgetItemDatasource()
запрашивается источник данных для текущего экземпляра сущности, и передается компонентуLookupPickerField
.Если в ячейке необходимо отобразить просто динамически сформированный текст, вместо компонента Label используйте класс
Table.PlainTextCell
. Это упростит отрисовку и сделает таблицу быстрее.Если в метод
addGeneratedColumn()
передан идентификатор колонки, не объявленной в XML-дескрипторе, то может понадобиться установить заголовок новой колонки следующим образом:carsTable.getColumn("colour").setCaption("Colour");
Существует также более декларативный подход, использующий XML-атрибут generator.
-
Метод
requestFocus()
позволяет установить фокус на определенное поле конкретной записи. Принимает два параметра: экземпляр сущности, определяющий строку и идентификатор колонки. Пример программной установки фокуса:table.requestFocus(item, "count");
-
Метод
scrollTo()
позволяет программно прокрутить таблицу до нужной записи. Метод принимает экземпляр сущности, определяющий нужную строку в таблице.Пример использования метода:
table.scrollTo(item);
-
Метод
setClickListener()
может избавить от необходимости добавлять генерируемые колонки с компонентами, если нужно нарисовать что-либо в ячейках и получать оповещения когда пользователь кликает на эти ячейки. Имплементация классаCellClickListener
, передаваемая в данный метод, получает текущий экземпляр сущности и идентификатор колонки. Содержимое ячеек будет завернуто в элементspan
со стилемcuba-table-clickable-cell
, который можно использовать для задания отображения ячеек.
-
Метод
setStyleProvider()
позволяет задать стиль отображения ячеек таблицы. Параметром метода должна быть реализация интерфейсаTable.StyleProvider
. МетодgetStyleName()
этого интерфейса вызывается таблицей отдельно для каждой строки и для каждой ячейки. Если метод вызван для строки, то первый параметр содержит экземпляр сущности, отображаемый этой строкой, а второй параметрnull
. Если же метод вызван для ячейки, то второй параметр содержит имя атрибута, отображаемого этой ячейкой.Пример задания стилей:
@Inject protected Table customersTable; @Override public void init(Map<String, Object> params) { customersTable.setStyleProvider(new Table.StyleProvider() { @Nullable @Override public String getStyleName(Entity entity, @Nullable String property) { Customer customer = (Customer) entity; if (property == null) { // style for row if (hasComplaints(customer)) { return"unsatisfied-customer"; } } else if (property.equals("grade")) { // style for column "grade" switch (customer.getGrade()) { case PREMIUM: return "premium-grade"; case HIGH: return "high-grade"; case MEDIUM: return "medium-grade"; default: return null; } } return null; } }); }
Далее нужно определить заданные для строк и ячеек стили в теме приложения. Подробная информация о создании темы находится в Создание темы приложения. Для веб-клиента новые стили определяются в файле
styles.scss
. Имена стилей, заданные в контроллере, совместно с префиксами, обозначающими строку или колонку таблицы, образуют CSS-селекторы. Например:.v-table-row.unsatisfied-customer { font-weight: bold; } .v-table-cell-content.premium-grade { background-color: red; } .v-table-cell-content.high-grade { background-color: green; } .v-table-cell-content.medium-grade { background-color: blue; }
-
Метод
addPrintable()
позволяет задать специфическое представление данных колонки при выводе в XLS-файл, осуществляемом стандартным действиемexcel
или напрямую с помощью классаExcelExporter
. Метод принимает идентификатор колонки и реализацию интерфейсаTable.Printable
для нее. Например:ordersTable.addPrintable("customer", new Table.Printable<Customer, String>() { @Override public String getValue(Customer customer) { return "Name: " + customer.getName; } });
Метод
getValue()
интерфейсаTable.Printable
должен возвращать данные, которые будут находиться в ячейке таблицы. Это может быть не только строка - метод может возвращать значения других типов, например, числовые данные или даты, и они будут представлены в XLS-файле соответствующим образом.Если форматированный вывод в XLS необходим для генерируемой колонки, нужно использовать реализацию интерфейса
Table.PrintableColumnGenerator
, передавая ее методуaddGeneratedColumn()
. Значение для вывода в ячейку XLS-документа задается в методеgetValue()
этого интерфейса:ordersTable.addGeneratedColumn("product", new Table.PrintableColumnGenerator<Order, String>() { @Override public Component generateCell(Order entity) { Label label = componentsFactory.createComponent(Label.NAME); Product product = order.getProduct(); label.setValue(product.getName() + ", " + product.getCost()); return label; } @Override public String getValue(Order entity) { Product product = order.getProduct(); return product.getName() + ", " + product.getCost(); } });
Если генерируемой колонке тем или иным способом не задано представления
Printable
, то в случае, если колонке соответствует атрибут сущности, будет выведено его значение, в противном случае не будет выведено ничего.
-
Метод
setItemClickAction()
позволяет задать действие, выполняемое при двойном клике на строке таблицы. Если такое действие не задано, при двойном клике таблица пытается найти среди своих действий подходящее в следующем порядке:-
Действие, назначенное на клавишу Enter посредством свойства
shortcut
. -
Действие с именем
edit
. -
Действие с именем
view
.Если такое действие найдено и имеет свойство
enabled = true
, оно выполняется.
-
-
Метод
setEnterPressAction()
позволяет задать действие, выполняемое при нажатии клавиши Enter. Если такое действие не задано, таблица пытается найти среди своих действий подходящее в следующем порядке:-
Действие, назначенное методом
setItemClickAction()
. -
Действие, назначенное на клавишу Enter посредством свойства
shortcut
. -
Действие с именем
edit
. -
Действие с именем
view
.
Если такое действие найдено и имеет свойство
enabled = true
, оно выполняется. -
- Атрибуты table
-
align - aggregatable - aggregationStyle - columnControlVisible - columnHeaderVisible - contextMenuEnabled - editable - enable - height - id - multiLineCells - multiselect - presentations - reorderingAllowed - settingsEnabled - showSelection - sortable - stylename - tabIndex - textSelectionEnabled - visible - width
- Элементы table
-
actions - buttonsPanel - columns - rows - rowsCount
- Атрибуты column
-
align - caption - captionProperty - collapsed - dateFormat - editable - generator - id - link - linkInvoke - linkScreen - linkScreenOpenType - maxTextLength - optionsDatasource - resolution - sortable - visible - width
- Элементы column
- Атрибуты aggregation
- Атрибуты rows
- Предопределенные стили table
-
borderless - compact - no-header - no-horizontal-lines - no-stripes - no-vertical-lines - small
- API
-
addGeneratedColumn - addPrintable - addColumnCollapseListener - applySettings - generateCell - getSelected - requestFocus - saveSettings - scrollTo - setClickListener - setEnterPressAction - setItemClickAction - setStyleProvider