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

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

Данный пример демонстрирует только изменение контекстного меню в таблице с помощью скрипта.

Начальный код расширения должен импортировать прямо или косвенно все остальные строки, чтобы затем объединить код в один пакет.

extensionManager.registerExtension({ (1)
    name: "GridContextMenuItem",
    version: "5.5.17",
    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)

    modalHost.dialogProps.header = "Предпросмотр"; (3)

    modalHost.dialogProps.maxWidth = "80vw"; (4)

    modalHost.dialogProps.maxHeight = "80vh"; (5)

    modalHost.dialogProps.maximizeButtonEnabled = true;
    modalHost.dialogProps.onMaximize = () => {
        modalHost.dialogProps.maximized = !modalHost.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 Показываем модальное окно.

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

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

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

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