DynamicDialog

Базовые вызовы

Содержимое окна — обычный компонент с пропами и событиями. Диалог закрывается изнутри через useC3DynamicDialogContext().close(value).

Результаты

Нажмите кнопки выше — здесь появятся результаты вызовов.

Входные параметры

Компонент C3DynamicDialog не имеет пропов: он рендерит диалог, который открыли программно. Все параметры задаются в вызове open(Component, options) из useC3DynamicDialog().

Параметры open(Component, options)

ИмяТипПо умолчаниюОписание
ComponentComponent—Обязательный первый аргумент: компонент, который будет отрисован внутри окна.
options.titlestring'' Заголовок. Попадает в aria-label. Пустая строка — шапка не рендерится.
options.widthstring'32rem' Ширина окна. Ограничена max-width: calc(100vw - var(--c3-margin-large)), поэтому длинные значения не ломают вёрстку.
options.propsRecord<string, unknown>{}Пропы компонента.
options.onRecord<string, Function>{}Обработчики событий компонента: имя события → функция.
options.closeOnBackdropbooleantrueЗакрывать по клику по подложке.
options.closeOnEscapebooleantrueЗакрывать по Escape.

Методы useC3DynamicDialog()

ИмяВозвращаетОписание
open(Component, options?)Promise<DynamicDialogResult>Показать компонент в окне и дождаться закрытия.
close(reason, result?)—Закрыть текущий диалог с указанием причины. Используется хостом.
dismiss(result?)—Закрыть текущий диалог программно: причина 'programmatic'.
reset()— Сбросить очередь: текущий и ожидающие диалоги резолвятся как закрытые программно.
contextRef<DynamicDialogState | null>Показываемый диалог.
isOpen()booleanЕсть ли активные диалоги: показанный или ожидающие в очереди.
useC3DynamicDialogContext()DynamicDialogContext | undefined Контекст текущего диалога. Вне окна возвращает undefined, а не бросает.

Результат

Промис open() резолвится объектом DynamicDialogResult: { result?: unknown, reason: DynamicDialogCloseReason }. Причина закрытия — 'action' (значение передал сам диалог через контекст), 'escape', 'backdrop' или 'programmatic'.

Описание

DynamicDialog открывает произвольный компонент в модальном окне. Он нужен, когда содержимое диалога слишком специфично для повторного использования: форма редактирования одной сущности, отчёт, мастер настройки. Обычный C3Modal требует состояния v-model:open и слота с разметкой в вызывающем компоненте, а здесь достаточно одной строки:

const { open } = useC3DynamicDialog() и await open(EditDialog, { props }).

Отличие от MessageBox: там содержимое фиксировано (сообщение, иконка, кнопки), здесь содержимое — любой компонент со своими пропами и событиями. MessageBox подходит для подтверждений, DynamicDialog — для форм и мастеров.

Состояние общее для приложения, поэтому open() можно вызвать из composable, стора или обработчика. Вызовы не конфликтуют: если окно уже открыто, следующее встаёт в очередь и показывается после закрытия текущего.

Хост C3DynamicDialog нужно разместить один раз в корневом макете (например, в app.vue), а не на каждой странице.

Дополнительная информация

  • Доступность: роль dialog, aria-modal="true"; заголовок дублируется в aria-label. Роль alertdialog не используется — это у MessageBox для подтверждений.
  • Фокус при открытии переносится на первый фокусируемый элемент внутри компонента, при закрытии возвращается на элемент, открывший окно.
  • Escape закрывает окно, Tab замыкает фокус внутри (фокус-тэп через trapFocus).
  • Пока открыт диалог, прокрутка страницы блокируется (lockBodyScroll).
  • Телепорт рендерится только на клиенте, поэтому SSR-разметка не расходится при нескольких таких компонентах.
  • Анимация появления использует переход c3-modal-* и отключается при prefers-reduced-motion.
  • Именованные слоты не поддерживаются: если содержимое требует слотов, заверните его в свой компонент и передайте в open() уже его.
  • Компонент не делается глубоко реактивным (shallowRef + markRaw), поэтому Vue не ругается на переданный компонент в консоли.

Пример использования

Диалог-форма, которая закрывается изнутри и сообщает результат вызывающему коду:

const EditDialog = defineComponent({ /* ... */ setup(props, { emit }) { const dialog = useC3DynamicDialogContext() return () => h('div', [/* поля */, h('button', { onClick: () => dialog?.close({ ok: true }) }, 'Готово')]) } })

const { open } = useC3DynamicDialog() const result = await open(EditDialog, { title: 'Профиль', props: { id: 42 } }) if (result.result) await save(result.result)

×