Расширить контекстное меню
Грид позволяет расширить функциональность контекстного меню при помощи расширений. Данный раздел описывает пример добавления нового пункта контекстного меню. Новый пункт контекстного меню позволяет открыть карточку в модальном окне или скрыть существующий элемент.
Ссылка на пример на GitHub: GridContextMenuItem.
Начальный код расширения должен импортировать прямо или косвенно все остальные строки, чтобы затем объединить код в один пакет.
extensionManager.registerExtension({ (1)
name: "GridContextMenuItem",
version: "6.1",
initialize() {
app.folderPluginProvider.addFactory(new GridContextMenuItemPluginFactory());
},
})
1 | Регистрация расширения позволяет корректно установить все обработчики событий, сервисы и прочие сущности web-приложения. |
Добавить новый пункт контекстного меню
Расширение добавляет пункт контекстного меню, который открывает карточку в модальном окне.
export const AddContextMenuItemProvider: TablePlugins.ServiceProvider<$ContextMenuOptions & $FolderGrid & $LayoutCardController & $DeviceType & $LayoutManager> = {
name: "AddContextMenuItemProvider",
description: "Добавляет пункт контекстного меню, который открывает карточку в модальном окне",
feature: GridContextMenuItemFeature,
composition: TableCompositionNames.Root,
addServices: (composition) => {
const { contextMenuOptions, folderGrid } = composition.services;
if (contextMenuOptions) {
const isAdded = contextMenuOptions.isAddedProvider(CONTEXT_MENU_ITEM_CUSTOM_PROVIDER_ID, TableCompositionNames.TableCell); (1)
if (!isAdded) {
const provider = {
id: CONTEXT_MENU_ITEM_CUSTOM_PROVIDER_ID, (2)
composition: TableCompositionNames.TableCell, (3)
getItemsToAdd: () => ([ (4)
{
id: "CONTEXT_MENU_CUSTOM_ITEM", (5)
name: "Предпросмотр карточки", (6)
action: (context: TableCompositions.Cell) => showCard(context, composition.services), (7)
blockId: folderGrid?.getContextMenuBlockNames().linkOperation, (8)
order: 0, (9)
}
])
} as IDataItemProvider;
contextMenuOptions.addItemProvider(provider);
}
}
}
};
1 | Поскольку метод addServices вызывается при каждой прорисовке, проверим не был ли добавлен ранее наш провайдер. |
2 | Уникальный ID провайдера, содержащего элементы списка контекстного меню. |
3 | Композиция, где будет вызвано контекстное меню. |
4 | Метод, который возвращает массив элементов контекстного меню. |
5 | Уникальный ID элемента контекстного меню.
В данном примере с помощью ID осуществляется доступ к скрытию элемента контекстного меню. |
6 | Отображаемое название элемента контекстного меню. |
7 | Метод, который будет вызван после клика на элемент контекстного меню. |
8 | Указание на расположение элемента в блоке элементов контекстного меню. |
9 | Порядковый номер расположения элемента в блоке элементов контекстного меню. |
Скрыть пункт контекстного меню
Следующий пример скрывает пункт "Открыть" в контекстном меню грида.
export const HideContextMenuItemProvider: TablePlugins.ServiceProvider<$ContextMenuOptions> = {
name: "HideContextMenuItemProvider",
description: "Скрывает пункт «Открыть» в контекстном меню",
feature: GridContextMenuItemFeature,
composition: TableCompositionNames.Root,
addServices: (composition) => {
const { contextMenuOptions } = composition.services;
if (contextMenuOptions) {
const isAdded = contextMenuOptions.isAddedFilter(CONTEXT_MENU_ITEM_CUSTOM_FILTER_ID, TableCompositionNames.TableCell); (1)
if (!isAdded) {
const filter = {
id: CONTEXT_MENU_ITEM_CUSTOM_FILTER_ID, (2)
composition: TableCompositionNames.TableCell, (3)
getItemsToHide: () => [CONTEXT_MENU_FOLDER_OPEN_ID] (4)
} as IDataItemFilter;
contextMenuOptions.addItemFilter(filter);
}
}
}
};
1 | Поскольку метод addServices вызывается при каждой прорисовке, проверим не был ли добавлен ранее наш фильтр. |
2 | Уникальный ID фильтра. |
3 | Композиция, где будет вызвано контекстное меню. |
4 | Метод, который возвращает массив ID элементов контекстного меню. |
Отображение модального окна
Данный пример демонстрирует создание и отображение модального окна.
export async function showCard(context: TableCompositions.Cell, services: $ContextMenuOptions & $FolderGrid & $LayoutCardController & $DeviceType & $LayoutManager) {
const modalHost = new CommonModalDialogHost("grid-context-menu__card-layout", services); (1)
(2)
const dialogProps = modalHost.dialogProps as CommonModalDialogProps;
dialogProps.header = "Предпросмотр"; (3)
dialogProps.maxWidth = "80vw"; (4)
dialogProps.maxHeight = "80vh"; (5)
dialogProps.maximizeButtonEnabled = true;
dialogProps.onMaximize = () => {
dialogProps.maximized = !dialogProps.maximized;
modalHost.forceUpdate(); (6)
}
modalHost.onCancelCallback = () => services.layoutManager.destroy(GRID_CONTEXT_MENU_SHOW_CARD_LOCATION_NAME); (7)
const renderLoading = (state: LoadingState) => <LoadingViewWithText state={state} className="padding-20 margin-30" />(8)
const loadLayout = async (): Promise<GenModels.LayoutViewModel> => { (9)
const model = await services.layoutCardController.view(context.data.row.entityId, PlatformModeConditionTypes.VIEW);
return model;
}
const dialogServices = addServices(services, modalHost.service, true); (10)
modalHost.renderCallback = () => (
<LocationContainerControl
async={true}
renderLoadingState={renderLoading}
customLayoutLoader={loadLayout} (11)
locationName={GRID_CONTEXT_MENU_SHOW_CARD_LOCATION_NAME}
services={dialogServices}
name={GRID_CONTEXT_MENU_SHOW_CARD_LOCATION_NAME} />
);
await modalHost.showDialog(); (12)
}
1 | Модальное окно. |
2 | Конфигурируем модальное окно. |
3 | Заголовок модального окна. |
4 | Максимальная ширина. |
5 | Максимальная высота. |
6 | Изменение отображения модального окна (свернуть / развернуть). |
7 | Обработчик закрытия модального окна. |
8 | Отображение текста загрузки разметки. |
9 | Получение разметки карточки в режиме просмотра. |
10 | Сервисы модального окна. |
11 | Тело модального окна. |
12 | Показываем модальное окно. |
Зарегистрируйте плагин в GridContextMenuItemPluginFactory
:
export class GridContextMenuItemPluginFactory implements IFolderPluginFactory {
id: string = "GridContextMenuItemPluginFactory";
getTablePlugins(): ITablePlugins[] {
return [
GridContextMenuItemPlugins
]
}
}