dataGrid
dataGrid отображает структурированные данные в строках и колонках и позволяет эффективно просматривать большие наборы данных.
XML-элемент |
|
|---|---|
Java-класс |
|
Основы
Для создания компонента используйте XML-элемент dataGrid и свяжите его с контейнером данных. Поддерживаются оба типа контейнеров: коллекции и KeyValue.
Затем укажите, какие атрибуты из контейнера вы хотите отобразить:
Чтобы создать компонент, добавьте XML-элемент dataGrid и свяжите его с контейнером данных. Компонент поддерживает контейнеры коллекций и контейнеры ключ-значение. Затем укажите атрибуты контейнера, которые нужно отобразить:
-
Если нужно отобразить только определённые атрибуты, добавьте элемент columns и вложите в него отдельные элементы column для каждого нужного атрибута.
-
Если фетч-план содержит ссылочный атрибут, этот атрибут будет отображаться по имени его экземпляра. Чтобы отобразить конкретный атрибут, добавьте его явно как в фетч-план, так и в элемент
column.
В примере таблица связана с контейнером коллекции, который заполняет usersDl. В XML выбираются отображаемые атрибуты сущности, а контроллер передаёт созданные данные загрузчику:
<data readOnly="true">
<collection id="ordersDc"
class="io.jmix.uisamples.entity.Order">
<fetchPlan extends="_local">
<property name="customer" fetchPlan="_local"/>
</fetchPlan>
<loader id="ordersLoader">
<query>
<![CDATA[select e from uisamples_Order e order by e.date]]>
</query>
</loader>
</collection>
</data>
<facets>
<dataLoadCoordinator auto="true"/>
</facets>
<layout>
<checkboxGroup id="dataGridSettingsGroup" label="Settings" themeNames="horizontal"/>
<dataGrid id="dataGrid" width="100%" minHeight="20em"
dataContainer="ordersDc">
<columns>
<column property="date"/>
<column property="customer"/>
<column property="amount"/>
<column property="description"/>
</columns>
</dataGrid>
</layout>
@ViewComponent
protected JmixCheckboxGroup<String> dataGridSettingsGroup;
@ViewComponent
protected DataGrid<Order> dataGrid;
@Subscribe
protected void onInit(InitEvent event) {
initSettingsGroup();
}
protected void initSettingsGroup() {
dataGridSettingsGroup.setItems("Sortable", "Resizable", "Column reordering allowed");
dataGridSettingsGroup.setTypedValue(Collections.singletonList("Sortable"));
}
@Subscribe("dataGridSettingsGroup")
protected void onDataGridSettingsGroupValueChange(
TypedValueChangeEvent<JmixCheckboxGroup<String>, Collection<String>> event) {
if (event.getValue() == null) {
return;
}
//clear
dataGrid.getAllColumns().forEach(col -> {
col.setSortable(false);
col.setResizable(false);
});
dataGrid.setColumnReorderingAllowed(false);
event.getValue()
.forEach(this::applyGridSettings);
}
protected void applyGridSettings(String setting) {
switch (setting) {
case "Sortable" -> dataGrid.getAllColumns().forEach(col -> col.setSortable(true));
case "Resizable" -> dataGrid.getAllColumns().forEach(col -> col.setResizable(true));
case "Column reordering allowed" -> dataGrid.setColumnReorderingAllowed(true);
}
}
dataGrid связанный с данными
Укажите dataContainer, чтобы отображать сущности из контейнера коллекции. Для скалярных и агрегатных результатов запроса используйте контейнер ключ-значение. Таблица отслеживает контейнер, поэтому при его перезагрузке или изменении строки обновляются.
Контейнер коллекции
Обычно dataGrid связывают с контейнером коллекции декларативно с помощью атрибута dataContainer. Этот подход используется в базовом примере.
Контейнер Key-Value
Свяжите таблицу с контейнером ключ-значение, если запрос возвращает скалярные значения или агрегаты. Колонки в примере соответствуют свойствам, объявленным в контейнере ключ-значение:
<data>
<keyValueCollection id="salesDc">
<loader id="salesLoader">
<query>
<![CDATA[select o.customer, sum(o.amount) from uisamples_Order o group by o.customer]]>
</query>
</loader>
<properties>
<property class="io.jmix.uisamples.entity.Customer"
name="customer"/>
<property datatype="decimal"
name="sum"/>
</properties>
</keyValueCollection>
</data>
<facets>
<dataLoadCoordinator auto="true"/>
</facets>
<layout>
<dataGrid id="salesDataGrid"
width="100%"
minHeight="20em"
dataContainer="salesDc">
<columns>
<column property="customer" header="Customer"/>
<column property="sum" header="Sum"/>
</columns>
</dataGrid>
</layout>
Программная привязка
Для контейнера, созданного в Java, укажите metaClass вместо dataContainer, чтобы колонки в XML могли получить метаданные сущности:
<dataGrid width="100%" id="dataGrid" metaClass="User">
<columns>
<column property="firstName"/>
<column property="lastName"/>
<column property="username"/>
<column property="joiningDate"/>
<column property="onboardingStatus"/>
</columns>
</dataGrid>
Затем оберните программный контейнер в ContainerDataGridItems и передайте его в сетку. Оболочка распространяет изменения контейнера и состояние выбора через API поставщика данных сетки:
@ViewComponent
private DataGrid<User> dataGrid;
@ViewComponent
private CollectionContainer<User> usersDc;
@Subscribe
public void onInit(InitEvent event) {
dataGrid.setItems(new ContainerDataGridItems<>(usersDc));
}
Программные колонки
addColumn() и addComponentColumn() позволяют создавать колонки в Java вместо XML.
addColumn() удобно использовать вместе с рендерерами, например с LocalDateRenderer, показанным в разделе LocalDateRenderer. addComponentColumn() подходит, когда в каждой ячейке должен отображаться UI-компонент.
В следующем примере создаётся таблица с заданным пользователем количеством колонок:
<hbox>
<integerField id="columnCountField" placeholder="Number of columns" value="3">
<validators>
<max value="10"/>
<min value="1"/>
</validators>
</integerField>
<button id="createDataGridBtn" text="Create DataGrid"/>
</hbox>
<vbox id="box" padding="false"/>
@ViewComponent
protected VerticalLayout box;
@ViewComponent
protected JmixIntegerField columnCountField;
@Autowired
protected DataComponents dataComponents;
@Autowired
protected UiComponents uiComponents;
@Autowired
protected Notifications notifications;
@Subscribe("createDataGridBtn")
protected void onCreateDataGridBtnClick(ClickEvent<JmixButton> event) {
box.removeAll();
Integer columnCount = columnCountField.getValue();
if (columnCount == null || columnCount < 1 || columnCount > 10) {
notifications.create("Column count must be between 1 and 10")
.withType(Notifications.Type.WARNING)
.withCloseable(false)
.show();
return;
}
KeyValueCollectionContainer container = createDataContainer(columnCount);
DataGrid<KeyValueEntity> dataGrid = createDataGrid(columnCount, container);
box.add(dataGrid);
}
protected DataGrid<KeyValueEntity> createDataGrid(Integer columnCount, KeyValueCollectionContainer container) {
DataGrid<KeyValueEntity> dataGrid = uiComponents.create(DataGrid.class);
dataGrid.setWidthFull();
dataGrid.setMinHeight("12em");
for (int col = 1; col <= columnCount; col++) {
dataGrid.addColumn("prop" + col, container.getEntityMetaClass().getPropertyPath("prop" + col))
.setHeader("Prop" + col);
}
dataGrid.setItems(new ContainerDataGridItems(container));
return dataGrid;
}
protected KeyValueCollectionContainer createDataContainer(Integer columnCount) {
KeyValueCollectionContainer container = dataComponents.createKeyValueCollectionContainer();
for (int col = 1; col <= columnCount; col++) {
container.addProperty("prop" + col, String.class);
}
container.setItems(loadData(columnCount));
return container;
}
protected Collection<KeyValueEntity> loadData(Integer columnCount) {
Collection<KeyValueEntity> list = new ArrayList<>();
for (int row = 0; row < 5; row++) {
KeyValueEntity entity = new KeyValueEntity();
for (int col = 1; col <= columnCount; col++) {
entity.setValue("prop" + col, "value" + row + col);
}
list.add(entity);
}
return list;
}
Множественный выбор
По умолчанию компонент работает в режиме одиночного выбора. Когда вы устанавливаете для selectionMode значение MULTI, появляется колонка флажка, позволяющий выбрать любое количество строк. Чтобы выбрать каждую строку, установите флажок в строке заголовка.
<select id="selectionModeSelect" label="Selection mode"/>
<hbox id="buttonsPanel" width="100%" wrap="true">
<button id="greetAllBtn" action="customersDataGrid.greetAll"/>
<button id="greetOneBtn" action="customersDataGrid.greetOne"/>
</hbox>
<dataGrid id="customersDataGrid"
width="100%"
minHeight="20em"
dataContainer="customersDc">
<actions>
<action id="greetAll" type="list_itemTracking" icon="COMMENTS" text="Greet all"/>
<action id="greetOne" type="list_itemTracking" icon="COMMENT" text="Greet single selected"/>
</actions>
<columns>
<column property="name"/>
<column property="lastName"/>
<column property="email"/>
<column property="age"/>
<column property="active"/>
<column property="grade"/>
</columns>
</dataGrid>
@ViewComponent
protected JmixSelect<Grid.SelectionMode> selectionModeSelect;
@ViewComponent
protected DataGrid<Customer> customersDataGrid;
@Subscribe
protected void onInit(InitEvent event) {
ComponentUtils.setItemsMap(selectionModeSelect, getSelectionModeItemsMap());
selectionModeSelect.setValue(Grid.SelectionMode.NONE);
}
@Subscribe("selectionModeSelect")
protected void onSelectionModeValueChange(
ComponentValueChangeEvent<JmixSelect<Grid.SelectionMode>, Grid.SelectionMode> event) {
customersDataGrid.setSelectionMode(event.getValue());
}
protected Map<Grid.SelectionMode, String> getSelectionModeItemsMap() {
return Arrays.stream(Grid.SelectionMode.values())
.collect(Collectors.toMap(Function.identity(), mode -> mode.name().replace('_', ' ')));
}
| Выбор диапазона с помощью Shift + щелчок и других сочетаний клавиш пока не поддерживается. |
Встроенное редактирование
Компонент поддерживает встроенное редактирование, позволяя пользователям переключаться между просмотром и редактированием данных таблицы. Встроенное редактирование можно активировать с помощью кнопок в колонке действий или двойным щелчком мыши.
|
Встроенное редактирование обновляет атрибуты сущностей в памяти. Для сохранения изменений в базе данных используйте следующие методы:
|
Колонка действий
Используйте editorActionsColumn для добавления кнопок Edit и Close рядом с каждой строкой. Они позволяют пользователям начать и завершить редактирование соответственно.
Колонка действий по умолчанию добавляется рядом с другими колонками. Если указано includeAll="true" - автоматически размещается крайней справа.
|
<dataGrid id="customersDataGridNonBuffered"
width="100%"
height="100%"
minHeight="20em"
dataContainer="customersDc">
<columns>
<column property="name" editable="true"/>
<column property="lastName" editable="true"/>
<column property="email"/>
<column property="age"/>
<column property="active"/>
<column property="grade" editable="true"/>
<editorActionsColumn key="nonBufferedEditorColumn">
<editButton icon="PENCIL" text="msg:///actions.Edit"/>
<closeButton icon="CHECK"/>
</editorActionsColumn>
</columns>
</dataGrid>
Буферизованный режим
При включённом буферизованном режиме пользователям необходимо подтверждать или отменять свои изменения, что снижает риск случайных правок. При переходе на другую строку внесённые изменения отменяются.
<dataGrid id="customersDataGridBuffered"
width="100%"
height="100%"
minHeight="20em"
dataContainer="customersDc"
editorBuffered="true">
<columns>
<column property="name" editable="true"/>
<column property="lastName" editable="true"/>
<column property="email"/>
<column property="age"/>
<column property="active"/>
<column property="grade" editable="true"/>
<editorActionsColumn key="bufferedEditorColumn">
<editButton icon="PENCIL" text="msg:///actions.Edit"/>
<saveButton icon="CHECK" themeNames="success"/>
<cancelButton icon="CLOSE" themeNames="error" text="msg:///actions.Cancel"/>
</editorActionsColumn>
</columns>
</dataGrid>
Редактирование по двойному клику
Иногда удобнее начинать встроенное редактирование, дважды щёлкнув по элементу.
<dataGrid width="100%" dataContainer="usersDc" id="dblClickTable">
<columns>
<column property="username"/>
<column property="firstName" editable="true"/>
<column property="lastName" editable="true"/>
<column property="active" editable="true"/>
<column property="onboardingStatus"/>
</columns>
</dataGrid>
@ViewComponent
private DataGrid<User> dblClickTable;
@ViewComponent
private GridMenuItem<Object> emailItem;
@Subscribe
public void onInit(InitEvent event) {
DataGridEditor<User> tableEditor = dblClickTable.getEditor();
dblClickTable.addItemDoubleClickListener(e -> {
tableEditor.editItem(e.getItem());
Component editorComponent = e.getColumn().getEditorComponent();
if (editorComponent instanceof Focusable) {
((Focusable) editorComponent).focus();
}
});
}
Автосохранение изменений
В стандартном экране списка загруженные сущности не объединяются в DataContext (если в XML-элементе загрузчика установлен атрибут readOnly="true"). Кроме того, в экранах списка обычно отсутствуют кнопки подтверждения, такие как OK или Save. Поэтому изменённые сущности необходимо явно сохранять в базе данных.
В небуферизованном режиме это можно сделать с помощью DataManager в обработчике события EditorCloseEvent следующим образом:
В буферизованном режиме выполните то же действие в обработчике EditorSaveEvent. В примере реализованы оба варианта:
@Autowired
private DataManager dataManager;
@Autowired
private Notifications notifications;
@ViewComponent
private CollectionContainer<Customer> customersDc;
@ViewComponent
private CollectionLoader<Customer> customersDl;
@ViewComponent
private JmixCheckbox immediateCheckbox;
@ViewComponent
private JmixButton saveButton;
private final Set<Customer> changedCustomers = new HashSet<>();
@Install(to = "customersDataGridBuffered.@editor", subject = "saveListener")
private void customersDataGridBufferedEditorSaveListener(final EditorSaveEvent<Customer> event) {
saveOrEnqueue(event.getItem());
}
@Install(to = "customersDataGridNonBuffered.@editor", subject = "closeListener")
private void customersDataGridNonBufferedEditorCloseListener(final EditorCloseEvent<Customer> event) {
saveOrEnqueue(event.getItem());
}
@Subscribe("immediateCheckbox")
public void onImmediateCheckboxComponentValueChange(final AbstractField.ComponentValueChangeEvent<JmixCheckbox, Boolean> event) {
saveButton.setEnabled(!event.getValue());
}
@Subscribe(id = "saveButton", subject = "clickListener")
public void onSaveButtonClick(final ClickEvent<JmixButton> event) {
saveEnqueuedChanges();
}
private void saveOrEnqueue(Customer customer) {
if (immediateCheckbox.getValue()) {
saveChanges(customer);
} else {
changedCustomers.add(customer);
}
}
private void saveChanges(Customer customer) {
// Save changed entity
Customer savedCustomer = dataManager.save(customer);
// Replace the original entity in the data container with the saved one
customersDc.replaceItem(savedCustomer);
// Note that if the original entity is merged into DataContext (this is the
// case when <loader readOnly="false">), the saved instance should be merged too
notifications.show("Changes saved to the database");
}
private void saveEnqueuedChanges() {
if (!changedCustomers.isEmpty()) {
// Save enqueued changes. The returned value is ignored because all data will be reloaded.
dataManager.saveAll(changedCustomers);
changedCustomers.clear();
notifications.show("Changes saved to the database");
customersDl.load();
}
}
|
Для генерации обработчиков в виде аннотированных методов используйте вкладку Handlers в Component Inspector Jmix студии, где обработчики событий редактора помечены префиксами Обработчики также можно добавить программно с помощью методов |
DataGridEditor
Интерфейс io.jmix.flowui.component.grid.editor.DataGridEditor предоставляет дополнительную функциональность редактора: настройку, открытие, сохранение и отмену редактирования строки, регистрацию обработчиков событий, а также служебные методы для определения компонентов редактирования колонок.
Для поддержки механизмов фреймворка, таких как контейнеры данных, источники значений и т.д., компонент редактирования колонки должен добавляться с использованием методов DataGridEditor (например, DataGridEditor#setColumnEditorComponent()), а не через прямое API колонки Column#setEditorComponent().
|
Пример использования:
@Autowired
private UiComponents uiComponents;
@ViewComponent
private DataGrid<User> editableUserTable;
@Subscribe
public void onInit(InitEvent event) {
DataGridEditor<User> editor = editableUserTable.getEditor(); (1)
editor.setColumnEditorComponent("timeZoneId", generationContext -> {
//noinspection unchecked
JmixComboBox<String> timeZoneField = uiComponents.create(JmixComboBox.class); (2)
timeZoneField.setItems(List.of(TimeZone.getAvailableIDs()));
timeZoneField.setValueSource(generationContext.getValueSourceProvider().getValueSource("timeZoneId"));
timeZoneField.setWidthFull();
timeZoneField.setClearButtonVisible(true);
timeZoneField.setRequired(true);
//noinspection unchecked,rawtypes
timeZoneField.setStatusChangeHandler(((Consumer) generationContext.getStatusHandler())); (3)
return timeZoneField; (4)
});
}
| 1 | Получить экземпляр DataGridEditor. |
| 2 | Экземпляр компонента JmixComboBox создаётся с помощью фабрики UiComponents. |
| 3 | Установить StatusChangeHandler. |
| 4 | Метод setColumnEditorComponent() возвращает визуальный компонент, который будет отображаться как редактор колонки. |
SupportsStatusChangeHandler
По умолчанию компоненты ввода (например, textField, comboBox) отображают сообщения об ошибках в тексте над собой. Такое поведение имеет недостатки при ограниченной области ячейки редактирования. Интерфейс io.jmix.flowui.component.SupportsStatusChangeHandler позволяет определить альтернативный способ отображения сообщений об ошибках. Компоненты, реализующие этот интерфейс, поддерживают делегирование обработки ошибок.
По умолчанию встроенный редактор использует StatusChangeHandler для установки сообщения об ошибке компонента в качестве его title.
Заголовок и подвал
Компонент может включать секции заголовка (header) и подвала (footer) для отображения дополнительной информации. Каждая секция может содержать одну или несколько строк, которые можно добавить с помощью следующих методов:
Метод |
Описание |
|---|---|
|
Добавляет новую строку в нижнюю часть секции заголовка. |
|
Добавляет новую строку в верхнюю часть секции заголовка. |
|
Добавляет новую строку в нижнюю часть секции подвала. |
|
Добавляет новую строку в верхнюю часть секции подвала. |
Ниже приведён пример dataGrid, который содержит объединённые ячейки в заголовке и вычисляемое значение в подвале:
<dataGrid id="dataGrid"
width="100%"
minHeight="20em"
dataContainer="countryGrowthDc"
themeNames="column-borders row-stripes">
<columns>
<column property="country"/>
</columns>
</dataGrid>
@ViewComponent
protected DataGrid<CountryGrowth> dataGrid;
@Autowired
protected MessageTools messageTools;
@Autowired
protected Metadata metadata;
protected DecimalFormat percentFormat;
@Subscribe
protected void onInit(InitEvent event) {
initPercentFormat();
initColumns();
initHeader();
}
@Subscribe
protected void onBeforeShow(BeforeShowEvent event) {
//because data is loaded
initFooter();
}
protected void initPercentFormat() {
percentFormat = (DecimalFormat) NumberFormat.getPercentInstance(UI.getCurrent().getLocale());
percentFormat.setMultiplier(1);
percentFormat.setMaximumFractionDigits(2);
}
protected void initColumns() {
MetaClass metaClass = metadata.getClass(CountryGrowth.class);
dataGrid.addComponentColumn(countryGrowth -> new Text(percentFormat.format(countryGrowth.getPrevYear())))
.setHeader(messageTools.getPropertyCaption(metaClass, "prevYear"))
.setKey("prevYear");
dataGrid.addComponentColumn(countryGrowth -> new Text(percentFormat.format(countryGrowth.getCurrYear())))
.setHeader(messageTools.getPropertyCaption(metaClass, "currYear"))
.setKey("currYear");
}
protected void initHeader() {
HeaderRow headerRow = dataGrid.prependHeaderRow();
HeaderRow.HeaderCell headerCell = headerRow.join(
dataGrid.getColumnByKey("prevYear"),
dataGrid.getColumnByKey("currYear")
);
Span gdpGrowth = new Span("GDP growth");
HorizontalLayout layout = new HorizontalLayout(gdpGrowth);
layout.setJustifyContentMode(FlexComponent.JustifyContentMode.CENTER);
headerCell.setComponent(layout);
}
protected void initFooter() {
FooterRow footerRow = dataGrid.appendFooterRow();
FooterRow.FooterCell countryCell = footerRow.getCell(dataGrid.getColumnByKey("country"));
Html html = new Html("<strong> Average: </strong>");
countryCell.setComponent(html);
footerRow.getCell(dataGrid.getColumnByKey("prevYear"))
.setText(percentFormat.format(getAverage("prevYear")));
footerRow.getCell(dataGrid.getColumnByKey("currYear"))
.setText(percentFormat.format(getAverage("currYear")));
}
protected double getAverage(String propertyId) {
double average = 0.0;
Collection<CountryGrowth> items = dataGrid.getGenericDataView().getItems().toList();
for (CountryGrowth countryGrowth : items) {
Double value = propertyId.equals("prevYear")
? countryGrowth.getPrevYear()
: countryGrowth.getCurrYear();
average += value != null ? value : 0.0;
}
return average / items.size();
}
Фильтрация по заголовкам колонок
Данные в dataGrid можно фильтровать с помощью фильтров по атрибутам, встроенных в заголовки колонок.
Вы можете указать, для каких колонок должен быть доступен фильтр, используя XML-атрибут filterable. В фильтруемых колонках в заголовках отображается иконка фильтра (). При клике на эту иконку появляется диалог с условием фильтрации по свойству. Если условие задано, иконка в соответствующей колонке подсвечивается.
Чтобы иконка фильтра всегда была видна, задайте колонке подходящую ширину с помощью атрибутов width или autoWidth. Не делайте колонку изменяемой по ширине, иначе пользователь сможет уменьшить её ширину и иконка фильтра станет невидимой.
Например:
<dataGrid id="customersDataGrid"
width="100%"
minHeight="20em"
dataContainer="customersDc">
<columns>
<column property="name" filterable="true"/>
<column property="lastName"/>
<column property="email"/>
<column property="age" filterable="true"/>
<column property="active" filterable="true"/>
<column property="grade" filterable="true"/>
</columns>
</dataGrid>
Фильтры свойств в заголовках колонок работают так же, как отдельные фильтры по свойствам и как genericFilter - они добавляют условия к загрузчику данных. В стандартном режиме эти условия преобразуются в JPQL-запрос и фильтруют данные на уровне базы данных.
Фильтруемые колонки можно использовать совместно с компонентами propertyFilter и genericFilter. Условия всех фильтров объединяются логическим оператором AND.
В настоящее время условия фильтрации в колонках не сохраняются в URL страницы. Это означает, что если пользователь применит фильтр, перейдёт в экран редактирования и затем вернётся обратно, фильтр будет сброшен.
Действия
Компонент dataGrid реализует интерфейс HasActions и может содержать стандартные действия со списками и пользовательские действия. Действия вызываются соответствующими кнопками или из контекстного меню, которое открывается щелчком правой кнопки мыши.
|
Чтобы добавить |
<hbox id="buttonsPanel" width="100%" wrap="true">
<button id="createBtn" action="customersDataGrid.create"/>
<button id="editBtn" action="customersDataGrid.edit"/>
<button id="removeBtn" action="customersDataGrid.remove"/>
<button id="greetingBtn" action="customersDataGrid.greeting"/>
</hbox>
<dataGrid id="customersDataGrid"
width="100%"
minHeight="20em"
dataContainer="customersDc">
<actions>
<action id="create" type="list_create">
<properties>
<property name="openMode" value="DIALOG"/>
</properties>
</action>
<action id="edit" type="list_edit">
<properties>
<property name="openMode" value="DIALOG"/>
</properties>
</action>
<action id="remove" type="list_remove"/>
<action id="greeting" type="list_itemTracking" icon="COMMENT" text="Greeting"/>
</actions>
<columns>
<column property="name"/>
<column property="lastName"/>
<column property="email"/>
<column property="age"/>
<column property="active"/>
<column property="grade"/>
</columns>
</dataGrid>
@ViewComponent
protected DataGrid<Customer> customersDataGrid;
@Autowired
protected Notifications notifications;
@Autowired
protected MetadataTools metadataTools;
@Subscribe("customersDataGrid.greeting")
protected void onCustomersDataGridGreetingActionPerformed(ActionPerformedEvent event) {
Customer customer = customersDataGrid.getSingleSelectedItem();
notifications.show(customer != null
? "Hello, " + metadataTools.getInstanceName(customer)
: "No selection");
}
Контекстное меню
Контекстное меню предоставляет альтернативный способ доступа к действиям через правую кнопку мыши. Каждое действие представлено отдельным пунктом меню.
Элемент contextMenu позволяет настроить список пунктов, организовав их с помощью разделителей и иерархической структуры.
<hbox id="buttonsPanel" width="100%" wrap="true">
<button id="createBtn" action="customersDataGrid.create"/>
<button id="editBtn" action="customersDataGrid.edit"/>
<button id="removeBtn" action="customersDataGrid.remove"/>
<button id="greetingBtn" action="customersDataGrid.greeting"/>
</hbox>
<dataGrid id="customersDataGrid"
width="100%"
minHeight="20em"
dataContainer="customersDc">
<contextMenu id="contextMenu">
<item text="CRUD" icon="TABLE">
<item action="customersDataGrid.create" icon="PLUS"/>
<item action="customersDataGrid.edit" icon="PENCIL"/>
<item action="customersDataGrid.remove" icon="TRASH"/>
</item>
<item action="customersDataGrid.greeting" icon="COMMENT"/>
<separator/>
<item id="customerItem"/>
<item action="customersDataGrid.getInfo" icon="INFO_CIRCLE_O"/>
</contextMenu>
<actions showInContextMenuEnabled="false">
<action id="create" type="list_create">
<properties>
<property name="openMode" value="DIALOG"/>
</properties>
</action>
<action id="edit" type="list_edit">
<properties>
<property name="openMode" value="DIALOG"/>
</properties>
</action>
<action id="remove" type="list_remove"/>
<action id="greeting" type="list_itemTracking" icon="COMMENT" text="Greeting"/>
<action id="getInfo" type="list_itemTracking" icon="INFO_CIRCLE_O" text="Get info"/>
</actions>
<columns>
<column property="name"/>
<column property="lastName"/>
<column property="email"/>
<column property="age"/>
<column property="active"/>
<column property="grade"/>
</columns>
</dataGrid>
@ViewComponent
protected DataGrid<Customer> customersDataGrid;
@Autowired
protected Notifications notifications;
@Autowired
protected Dialogs dialogs;
@Autowired
protected MetadataTools metadataTools;
@ViewComponent
protected GridMenuItem<Customer> customerItem;
@Install(to = "contextMenu", subject = "dynamicContentHandler")
public boolean contextMenuDynamicContentHandler(Customer customer) {
if (customer == null) {
return false;
}
customerItem.setText(metadataTools.getInstanceName(customer));
return true;
}
@Subscribe("customersDataGrid.greeting")
public void onCustomersDataGridGreetingActionPerformed(ActionPerformedEvent event) {
Customer customer = customersDataGrid.getSingleSelectedItem();
notifications.show(customer != null
? "Hello, " + metadataTools.getInstanceName(customer)
: "No selection");
}
@Subscribe("customersDataGrid.getInfo")
public void onCustomersDataGridGetInfoActionPerformed(ActionPerformedEvent event) {
Customer customer = customersDataGrid.getSingleSelectedItem();
dialogs.createMessageDialog()
.withContent(
customer != null
? getMessageDialogContent(customer)
: new Span("No selection")
)
.open();
}
protected Component getMessageDialogContent(Customer customer) {
return new Html("""
<div>
<strong>Name:</strong> %s<br/>
<strong>Age:</strong> %s<br/>
<strong>Email:</strong> %s
</div>
""".formatted(metadataTools.getInstanceName(customer), customer.getAge(), customer.getEmail()));
}
Рендереры
Рендереры настраивают отображение ячеек колонок. В этом разделе описаны рендереры, специфичные для колонок dataGrid. Общие API рендереров, такие как ComponentRenderer, LitRenderer и FragmentRenderer, описаны в разделе Рендереры.
Рендереры можно определить следующими способами:
-
Декларативно в XML - используйте предопределённые рендереры
numberRenderer,localDateRenderer,localDateTimeRenderer,detailLinkRendererиdetailButtonRendererвнутри элементаcolumn. -
С помощью аннотации
@Supply- предоставляйте пользовательский рендерер из контроллера экрана. -
С помощью
fragmentRenderer- используйте общий механизм рендеринга на основе фрагментов, описанный в Рендерер фрагментов. -
С помощью
addColumn()иaddComponentColumn()- создавайте колонки в Java и настраивайте рендереры программно. См. Программные колонки.
|
Чтобы добавить рендерер в Jmix Studio, выберите элемент |
LocalDateRenderer
LocalDateRenderer отвечает за отображение дат в формате значений типа LocalDate.
В элементе column таблицы присутствует вложенный элемент localDateRenderer, который содержит необязательный атрибут nullRepresentation и обязательный атрибут format для строки формата.
<column property="joiningDate">
<localDateRenderer format="MMM dd, yyyy"/>
</column>
Атрибут nullRepresentation используется для задания текстового отображения значений null.
Ниже приведён пример использования LocalDateRenderer с методом addColumn():
@ViewComponent
private DataGrid<User> usersDtGr;
@Subscribe
public void onInit(InitEvent event) {
usersDtGr.addColumn(new LocalDateRenderer<>(
User::getJoiningDate,
() -> DateTimeFormatter.ofLocalizedDate(
FormatStyle.MEDIUM)))
.setHeader("Joining date");
}
LocalDateTimeRenderer
LocalDateTimeRenderer отвечает за отображение дат в формате значений типа LocalDateTime.
В элементе column таблицы присутствует вложенный элемент localDateTimeRenderer, который содержит необязательный атрибут nullRepresentation и обязательный атрибут format, задающий строку формата.
<column property="passwordExpiration">
<localDateTimeRenderer format="dd/MM/YYYY HH:mm:ss"/>
</column>
Атрибут nullRepresentation используется для задания текстового отображения значений null.
Number Renderer
Отображает числовые значения в колонке.
<column property="factor">
<numberRenderer numberFormat="#,#00.0000"/>
</column>
Укажите ровно один из атрибутов format или numberFormat. Если не указан ни один из них или указаны оба, фреймворк выбросит GuiDevelopmentException. Используйте необязательный атрибут nullRepresentation, чтобы задать отображение null. Атрибут numberFormat использует синтаксис java.text.DecimalFormat.
DetailLinkRenderer
Отображает ссылку, открывающую экран редактирования текущей сущности.
<dataGrid width="100%" dataContainer="usersDc">
<columns>
<column property="username">
<detailLinkRenderer viewId="User.detail"
target="BLANK"
classNames="detail-link"
css="font-weight: 600;"/>
</column>
<column property="firstName"/>
<column property="lastName"/>
</columns>
</dataGrid>
Поддерживаемые атрибуты:
-
viewClass,viewIdзадают целевой экран. Рендерер определяет экран в следующем порядке:viewClass,viewId, экран редактирования по умолчанию. -
textзадаёт текст ссылки. Если атрибут не указан, рендерер использует форматированное значение привязанного свойства колонки. -
targetзадаёт цель ссылки. -
classNames,cssприменяют стили.
Целевой экран должен иметь зарегистрированный маршрут ровно с одним параметром маршрута, а экземпляр сущности должен уже иметь ненулевой id. Для маршрутов без параметров или с несколькими параметрами настраивайте рендерер из Java-кода и передавайте собственный URL с помощью DetailLinkRenderer.withHrefProvider().
DetailButtonRenderer
Отображает кнопку, открывающую экран редактирования текущей сущности.
<dataGrid width="100%" dataContainer="stepsDc">
<columns>
<column property="name">
<detailButtonRenderer viewId="Step.detail"
icon="vaadin:edit"
openMode="DIALOG"
themeNames="tertiary-inline small"
classNames="detail-button"
css="color: var(--lumo-primary-text-color);"/>
</column>
<column property="duration"/>
<column property="sortValue"/>
</columns>
</dataGrid>
Поддерживаемые атрибуты:
-
viewClass,viewIdзадают целевой экран. Рендерер определяет экран в следующем порядке:viewClass,viewId, экран редактирования по умолчанию. -
openModeуправляет способом открытия экрана:NAVIGATION(по умолчанию) илиDIALOG. -
textзадаёт текст кнопки. Если атрибут не указан, рендерер использует форматированное значение привязанного свойства колонки. Для колонок только сkeyзадавайте его явно. -
iconзадаёт значок кнопки. Его можно определить через атрибут или вложенный элементicon. -
themeNames,classNames,cssприменяют стили.
Detail Renderers в колонках, не связанных со свойством
DetailLinkRenderer и DetailButtonRenderer можно использовать в колонках, которые задаются через атрибут key, а не привязываются к атрибуту сущности с помощью атрибута property.
<dataGrid width="100%" dataContainer="usersDc">
<columns>
<column property="username"/>
<column key="openUser" header="Open">
<detailButtonRenderer viewId="User.detail"
text="Edit"
openMode="DIALOG"/>
</column>
</columns>
</dataGrid>
В этом случае задайте text ссылки или кнопки явно, потому что привязанное значение свойства отсутствует.
TextRenderer
TextRenderer отображает обычный текст, переданный из Java-кода.
<column key="status" header="Status"/>
@Supply(to = "userStepsDataGrid.status", subject = "renderer")
private Renderer<UserStep> userStepsDataGridStatusRenderer() {
return new TextRenderer<>(userStep ->
isOverdue(userStep) ? "Overdue!" : "");
}
Обычно этот рендерер задаётся из Java-кода с помощью обработчика renderer или аннотации @Supply.
ComponentRenderer
Отображает в каждой ячейке пользовательский компонент. Используйте этот рендерер для интерактивного или составного содержимого: флажка, изображения или кнопки.
| Сведения о доступных конструкторах, общем поведении и особенностях производительности смотрите в разделе Рендерер компонентов. |
В следующем примере в колонке active отображается флажок только для чтения, а в колонке grade — значок.
<dataGrid id="customersDataGrid"
width="100%"
minHeight="20em"
dataContainer="customersDc">
<columns>
<column property="name"/>
<column property="lastName"/>
<column property="email"/>
<column property="age"/>
<column property="active"/>
<column property="grade"/>
</columns>
</dataGrid>
@Autowired
protected UiComponents uiComponents;
@Autowired
protected Messages messages;
@Supply(to = "customersDataGrid.active", subject = "renderer")
protected Renderer<Customer> activeComponentRenderer() {
return new ComponentRenderer<>(
() -> {
JmixCheckbox checkbox = uiComponents.create(JmixCheckbox.class);
checkbox.setReadOnly(true);
return checkbox;
},
(checkbox, customer) -> checkbox.setValue(customer.isActive())
);
}
@Supply(to = "customersDataGrid.grade", subject = "renderer")
protected Renderer<Customer> statusComponentRenderer() {
return new ComponentRenderer<>(this::createGradeComponent, this::gradeComponentUpdater);
}
protected Span createGradeComponent() {
Span span = uiComponents.create(Span.class);
span.getElement().getThemeList().add("badge");
return span;
}
protected void gradeComponentUpdater(Span span, Customer customer) {
if (customer.getGrade() != null) {
span.setText(messages.getMessage(CustomerGrade.class, customer.getGrade().name()));
switch (customer.getGrade()) {
case STANDARD -> span.getElement().getThemeList().add("contrast");
case HIGH -> span.getElement().getThemeList().add("success");
case PREMIUM -> span.getElement().getThemeList().add("primary");
}
} else {
span.setText("No data");
}
}
Детализация элементов
Компонент позволяет раскрывать строки и показывать дополнительные сведения об элементах. Для этого используйте метод setItemDetailsRenderer(). Он принимает ComponentRenderer, который определяет отображение подробных сведений.
Атрибут detailsVisibleOnClick определяет, открываются ли подробные сведения при нажатии на строку. Если их должно открывать другое событие, установите атрибут в false.
<dataGrid id="customersDataGrid"
width="100%"
minHeight="20em"
dataContainer="customersDc">
<columns>
<column property="name"/>
<column property="lastName"/>
</columns>
</dataGrid>
@ViewComponent
protected DataGrid<Customer> customersDataGrid;
@Autowired
protected CustomerDetailsGenerator detailsGenerator;
@Subscribe
protected void onInit(InitEvent event) {
detailsGenerator.setReadOnlyMode(true);
customersDataGrid.setItemDetailsRenderer(createCustomerDetailsRenderer());
}
protected ComponentRenderer<FormLayout, Customer> createCustomerDetailsRenderer() {
return new ComponentRenderer<>(detailsGenerator::createCustomerDetailsRenderer, detailsGenerator::setCustomer);
}
Сортировка
В этом разделе показана кастомизация сортировки для отдельного компонента dataGrid. О кастомизации сортировки для всего приложения см. Сортировка.
|
Любая колонка таблицы может использоваться для сортировки отображаемых данных. При нажатии на заголовок колонки в таблице активируется специальный индикатор, который показывает текущую колонку сортировки и направление сортировки (по возрастанию или убыванию). Последующие нажатия на тот же заголовок будут переключать направление сортировки на противоположное.
|
Атрибуты-перечисления сортируются по значениям В результате порядок сортировки может отличаться от видимого порядка значений перечисления в |
Сортировка по нескольким столбцам
Данные можно сортировать одновременно по нескольким колонкам. В этом случае первая выбранная колонка определяет основной критерий сортировки, вторая колонка задаёт дополнительный критерий, а последующие колонки устанавливают второстепенные критерии сортировки.
Настройка осуществляется с помощью атрибутов multiSort, multiSortOnShiftClickOnly и multiSortPriority.
Пример:
<dataGrid id="customersDataGrid"
width="100%"
minHeight="20em"
dataContainer="customersDc"
multiSort="true"
multiSortPriority="APPEND">
<columns>
<column property="name"/>
<column property="lastName"/>
<column property="email"/>
<column property="age"/>
<column property="active"/>
<column property="grade"/>
</columns>
</dataGrid>
Компаратор колонки
Используйте DataGridColumn#setComparator() для определения пользовательской логики сортировки конкретного колонки, когда сортировка выполняется в памяти. Сортировка в памяти используется, если у контейнера нет загрузчика, либо если загружена только первая страница и количество загруженных элементов меньше размера страницы.
В следующем примере атрибут Department.num сортируется как число, хотя тип этого атрибута - String:
<dataGrid id="inMemoryDepartmentsDataGrid"
width="100%"
dataContainer="inMemoryDepartmentsDc">
<columns>
<column property="name"/>
<column property="num"/>
</columns>
</dataGrid>
private void initInMemoryComparator() {
inMemoryDepartmentsDc.setItems(dataManager.load(Department.class)
.query("select e from Department e")
.list());
inMemoryDepartmentsDataGrid.getColumnByKey("num")
.setComparator(Comparator.comparing(
department -> department.getNum() == null ? null : Integer.valueOf(department.getNum()),
Comparator.nullsFirst(Integer::compareTo)));
}
Делегат сортировки
Если таблица перезагружает данные из базы, настройте делегат построения сортировки. Он получает инструкции сортировки от таблицы и возвращает объект DataGridSort, позволяя переопределить сортировку в памяти, в базе данных или обе сразу.
В следующем примере колонка customer сортируется по имени и фамилии клиента:
<simplePagination id="pagination"
dataLoader="ordersDl"
itemsPerPageDefaultValue="4"/>
<dataGrid id="ordersDataGrid"
width="100%"
minHeight="20em"
dataContainer="ordersDc">
<columns>
<column property="date"/>
<column property="customer"/>
<column property="amount"/>
</columns>
</dataGrid>
@Install(to = "ordersDataGrid", subject = "sortBuilderDelegate")
public DataGridSort ordersDataGridSortBuilderDelegate(DataGridSortContext<Order> context) {
return DataGridSortBuilder.create(context)
.replaceSort("customer", List.of("{E}.customer.name", "{E}.customer.lastName"))
.build();
}
Сортировка вычисляемой колонки
Делегат сортировки также полезен для колонок, которые не привязаны к атрибуту сущности. В следующем примере колонка fullName формируется из firstName и lastName, а делегат сортировки сопоставляет эту синтетическую колонку и с выражениями JPQL, и с компаратором для сортировки в памяти:
<dataGrid id="fullNameUsersDataGrid"
width="100%"
dataContainer="usersDc">
<columns>
<column key="fullName" header="Full name" sortable="true"/>
<column property="username"/>
<column property="department.name"/>
<column property="onboardingStatus"/>
</columns>
</dataGrid>
private void initComputedColumnSortBuilder() {
fullNameUsersDataGrid.setSortBuilderDelegate(sortContext ->
DataGridSortBuilder.create(sortContext)
.replaceSort("fullName",
List.of("{E}.firstName", "{E}.lastName"),
Comparator.comparing(User::getFirstName,
Comparator.nullsFirst(String::compareTo))
.thenComparing(User::getLastName,
Comparator.nullsFirst(String::compareTo)))
.build());
}
@Supply(to = "fullNameUsersDataGrid.fullName", subject = "renderer")
protected Renderer<User> fullNameUsersDataGridFullNameRenderer() {
return new TextRenderer<>(user ->
((user.getFirstName() == null ? "" : user.getFirstName()) + " "
+ (user.getLastName() == null ? "" : user.getLastName())).trim());
}
Агрегация данных
Компонент поддерживает агрегирование значений в строках. Если агрегирование включено, отображается дополнительная строка с агрегированными значениями. Например:
<dataGrid id="ordersDataGrid"
width="100%"
minHeight="20em"
dataContainer="ordersDc"
aggregatable="true"
aggregationPosition="TOP">
<columns>
<column property="date"/>
<column property="customer"/>
<column property="customer.grade">
<aggregation
strategyClass="io.jmix.uisamples.view.flowui.components.datagrid.aggregation.DataGridCustomerGradeAggregation"/>
</column>
<column property="amount">
<aggregation type="SUM"/>
</column>
<column property="description"/>
</columns>
</dataGrid>
В атрибуте strategyClass элемента aggregation можно указать класс с пользовательской логикой агрегирования:
Такой класс должен реализовывать интерфейс AggregationStrategy. Например:
@Autowired
public Messages messages;
@Override
public String aggregate(Collection<CustomerGrade> propertyValues) {
CustomerGrade mostFrequent = null;
long max = 0;
if (CollectionUtils.isNotEmpty(propertyValues)) {
for (CustomerGrade grade : CustomerGrade.values()) {
long current = propertyValues.stream()
.filter(grade::equals)
.count();
if (current > max) {
mostFrequent = grade;
max = current;
}
}
}
if (mostFrequent != null) {
String key = CustomerGrade.class.getSimpleName() + "." + mostFrequent.name();
return String.format("%s: %d/%d", messages.getMessage(CustomerGrade.class, key), max, propertyValues.size());
}
return "NaN";
}
@Override
public Class<String> getResultClass() {
return String.class;
}
Отображение при отсутствии данных
Если в таблице нет данных, область между заголовком и нижним колонтитулом по умолчанию остаётся пустой. Настройте пустое состояние, чтобы вывести сообщение или UI-компонент об отсутствии элементов.
-
Используйте атрибут
emptyStateTextдля определения текста, который будет отображаться при пустой таблице.<dataGrid id="dataGridEmptyState" dataContainer="customersDc" width="100%" emptyStateText="No customers found"> <columns> <column property="firstName"/> <column property="lastName"/> <column property="age"/> <column property="martialStatus"/> </columns> </dataGrid>Данный атрибут имеет приоритет над компонентом пустого состояния, настроенным через метод setEmptyStateComponent(Component)в контроллере экрана и над элементомemptyStateComponentв XML-дескрипторе. Установка значенияemptyStateTextприведёт к удалению любого ранее заданного компонента. -
Для отображения компонента при отсутствии данных используйте элемент
emptyStateComponent.<hbox id="buttonsPanel" width="100%" wrap="true"> <button id="unloadBtn" action="customersDataGrid.unload"/> </hbox> <dataGrid id="customersDataGrid" width="100%" minHeight="20em" dataContainer="customersDc"> <actions> <action id="unload" icon="ERASER" text="msg://customersDataGrid.unload.text" enabled="false"/> </actions> <columns> <column property="name"/> <column property="lastName"/> <column property="email"/> <column property="age"/> <column property="active"/> <column property="grade"/> </columns> <emptyStateComponent> <vbox padding="false" height="100%" justifyContent="CENTER" alignItems="CENTER"> <h3 text="msg://emptyState.text"/> <button id="loadBtn" text="msg://loadBtn.text" icon="REFRESH" themeNames="primary"/> </vbox> </emptyStateComponent> </dataGrid>@ViewComponent private CollectionContainer<Customer> customersDc; @ViewComponent private CollectionLoader<Customer> customersDl; @ViewComponent("customersDataGrid.unload") private Action unloadAction; @Subscribe("customersDataGrid.unload") public void onCustomersDataGridUnloadActionPerformed(ActionPerformedEvent event) { customersDc.getMutableItems().clear(); unloadAction.setEnabled(false); } @Subscribe("loadBtn") public void onLoadBtnClick(ClickEvent<JmixButton> event) { customersDl.load(); unloadAction.setEnabled(true); }После настройки
emptyStateComponentвы можете работать с вложенным компонентом как обычно, включая настройку его стилей и создание обработчиков событий.Установка этого компонента отменяет:
-
любой текст пустого состояния, заданный методом
setEmptyStateText(String)в контроллере экрана; -
атрибут
emptyStateTextв XML-дескрипторе экрана.
-
Варианты темы
Используйте атрибут themeNames, чтобы настроить тему компонента.
| Вариант | Описание | Поддерживается в |
|---|---|---|
|
Добавляет вертикальные границы между колонками. |
Aura, Lumo |
|
Уменьшает высоту строк и интервалы. |
Lumo |
|
Удаляет внешнюю границу вокруг сетки. |
Aura, Lumo |
|
Удаляет горизонтальные границы между строками. |
Aura, Lumo |
|
Чередует цвета фона строк для улучшения читаемости. |
Aura, Lumo |
|
Позволяет содержимому ячеек переноситься на несколько строк вместо обрезки. |
Aura, Lumo |
Атрибуты
dataGrid имеет следующие уникальные атрибуты:
| Имя | Описание | По умолчанию |
|---|---|---|
Если значение равно Использование этой функции не рекомендуется при работе с большим количеством элементов, так как это может вызвать проблемы с производительностью. |
|
|
Если значение |
|
|
Если данные в компоненте — aggregatable, определяет, отображается ли строка агрегации выше или ниже других строк. Возможные значения: |
|
|
Если значение |
|
|
Если значение |
|
|
Определяет, где можно оставить перетаскиваемую строку. Возможные значения: |
– |
|
При значении - пользователь должен подтверждать изменения нажатием кнопки подтверждения; - предусмотрена возможность отмены внесённых изменений. В небуферизированном режиме изменения применяются сразу, без подтверждения. |
|
|
Текст, отображаемый при отсутствии данных. Чтобы удалить текущее содержимое, укажите |
– |
|
При значении |
|
|
При значении |
|
|
Определяет, будет ли выбранный колонка добавлен в конец или начало списка отсортированных колонок. Возможные значения: |
|
|
Определяет поведение при обработке вложенных свойств, которые могут содержать значения null в цепочке свойств. Допустимые значения: |
|
|
Определяет размер страницы, то есть количество элементов, одновременно получаемых от провайдера данных. |
|
|
Если значение |
|
|
Устанавливает режим выделения элементов. Допустимые значения: |
|
Элементы
Элементы dataGrid предоставляют широкий набор возможностей для управления внешним видом, поведением и функциональностью колонок как в целом, так и по отдельности.
|
Чтобы добавить элемент в выбранный компонент, нажмите кнопку Add в панели инспектора Jmix UI. |
columns
Элемент columns позволяет задать набор атрибутов для отображения и поведения для всех колонок.
XML-элемент |
|
|---|---|
Атрибуты |
exclude - includeAll - resizable - sortable |
Элементы |
Название |
Описание |
Значение по-умолчанию |
|---|---|---|
Исключает отображение определённых атрибутов. Несколько атрибутов следует перечислять через запятую. Например: |
– |
|
Если значение равно |
– |
|
При значении |
|
|
Если значение равно |
|
column
Элемент column определяет отдельную колонку. Атрибуты, заданные для отдельной колонки, переопределяют атрибуты, установленные для всех колонок.
XML-элемент |
|
|---|---|
Атрибуты |
autowidth - editable - filterable - flexGrow - footer - frozen - header - key - property - resizable - sortable - textAlign - visible - width |
Обработчики |
AttachEvent - DataGridColumnVisibilityChangedEvent - DetachEvent - partNameGenerator - renderer - tooltipGenerator |
Элементы |
Агрегация - FragmentRenderer - LocalDateRenderer - LocalDateTimeRenderer - NumberRenderer - DetailLinkRenderer - DetailButtonRenderer |
Название |
Описание |
Значение по-умолчанию |
|---|---|---|
Если значение равно |
|
|
Если значение равно |
|
|
Если значение равно |
|
|
Задаёт коэффициент растяжения колонки. При значении |
|
|
Задаёт текст в нижней части колонки (футере). Значением атрибута может быть либо сам текст, либо ключ из пакета сообщений. В случае использования ключа значение должно начинаться с префикса |
– |
|
Если значение равно |
|
|
Задаёт текст заголовка колонки. Значением атрибута может быть либо сам текст, либо ключ из пакета сообщений. В случае использования ключа значение должно начинаться с префикса |
– |
|
Задаёт пользовательский идентификатор для привязки к этой колонке. Этот ключ можно использовать для последующего получения колонки с помощью метода Ключ должен быть уникальным в пределах |
– |
|
Указывает имя атрибута сущности, который будет отображаться в колонке. Это может быть атрибут корневой сущности, например, |
– |
|
Если значение равно |
|
|
Если значение равно |
|
|
Задаёт выравнивание текста с возможными значениями: |
|
|
Если значение |
|
|
Задаёт ширину колонки в виде CSS-строки. |
– |
Название |
Описание |
|---|---|
Срабатывает при изменении видимости колонки через компонент gridColumnVisibility. |
|
Генерирует части CSS-классов для этой колонки на основе заданных условий. Это позволяет настраивать внешний вид ячеек в зависимости от отображаемых данных. См. интерактивный пример. |
|
Отображает содержимое колонки с помощью текста или компонентов. См. TextRenderer и ComponentRenderer. |
|
Генерирует всплывающую подсказку для ячейки колонки на основе заданных условий. См. интерактивный пример. |
contextMenu
Элемент contextMenu позволяет расположить пункты контекстного меню в порядке, отличном от стандартного. Меню открывается щелчком правой кнопки мыши. См. пример.
XML-элемент |
|
|---|---|
Атрибуты |
id - classNames - css - enabled - visible |
Обработчики |
AttachEvent - DetachEvent - GridContextMenuOpenedEvent - openedChangeEvent - dynamicContentHandler |
Элементы |
элемент - разделитель |
Название |
Описание |
|---|---|
Срабатывает при изменении состояния открытия контекстного меню. Может возвращать целевой элемент или идентификатор целевого колонки, позволяя меню отображать пункты в зависимости от выбранного элемента. |
|
Срабатывает при изменении состояния открытия контекстного меню. |
|
Обрабатывает динамическое обновление меню при открытии, например добавление пунктов или изменение их содержимого. См. пример. |
emptyStateComponent
Элемент emptyStateComponent определяет компонент, отображаемый при отсутствии данных. Чтобы удалить текущее содержимое, укажите null. См. Отображение при отсутствии данных.