Расширить контекстное меню

Грид позволяет расширить функциональность контекстного меню при помощи расширений. Данный раздел описывает пример добавления нового пункта контекстного меню. Новый пункт контекстного меню позволяет открыть карточку в модальном окне или скрыть существующий элемент.

Ссылка на пример на 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
        ]
    }
}

Проверка примера

  1. Откройте папку с таблицей и вызовите контекстное меню у произвольной карточки.

  2. Кликните на пункт "Предпросмотр карточки" в контекстном меню.

  3. Убедитесь, что открылось модальное окно "Предпросмотр", в котором отображается разметка просмотра выбранной карточки.