К статье
Практический материал

Разработка и Конфигурация · 12 мин

Как задать вопрос пользователю в управляемой форме 1С

Как задать вопрос в управляемой форме 1С: метод ПоказатьВопрос, ОписаниеОповещения, режимы диалога, примеры кода и типичные ошибки разработчиков.

В управляемых формах 1С нельзя использовать привычный модальный вызов Вопрос() из обычного приложения: модальные окна заблокированы в веб-клиенте и не рекомендованы в тонком клиенте. Вместо этого платформа предлагает асинхронный механизм — метод ПоказатьВопрос() с передачей описания оповещения, которое выполнится после ответа пользователя.

Асинхронная модель меняет привычную логику кода. Ответ пользователя возвращается не в строку вызова вопроса, а в отдельную процедуру-обработчик. Это требует перестройки алгоритмов: всё, что зависит от ответа, должно выполняться в процедуре оповещения, а не после строки с вопросом.

В статье разобран полный цикл работы с вопросами в управляемой форме: синтаксис ПоказатьВопрос, настройка кнопок диалога через РежимДиалогаВопрос, передача дополнительных параметров в обработчик, обработка таймаута и типичные ошибки, которые приводят к неработающему коду.

Почему модальный Вопрос() не работает в управляемых формах

В обычном приложении вопрос задавался одной строкой: Если Вопрос("Продолжить?", РежимДиалогаВопрос.ДаНет) = КодВозвратаДиалога.Да Тогда .... Такой вызов блокирует интерфейс до ответа пользователя, что несовместимо с архитектурой веб-клиента, где каждое блокирующее окно останавливает работу браузерного скрипта целиком.

Поэтому в режиме управляемого приложения платформа по умолчанию запрещает модальные вызовы. В конфигураторе это регулируется свойством конфигурации «Режим использования модальности»: значение «Использовать» разрешает старые вызовы, «Использовать с предупреждением» выводит предупреждение в журнал регистрации, «Не использовать» приводит к ошибке при попытке вызвать модальный метод.

Даже если в вашей базе модальность разрешена, полагаться на неё не стоит: код не запустится в веб-клиенте, а при обновлении конфигурации поставщиком режим может измениться. Правильный подход — сразу писать асинхронно через ПоказатьВопрос.

Базовый синтаксис: ПоказатьВопрос и ОписаниеОповещения

Минимальный рабочий сценарий состоит из двух частей: кода, который показывает вопрос, и процедуры-обработчика, которая получает ответ. Описание оповещения связывает их между собой.

&НаКлиенте

Процедура УдалитьСтроку(Команда)

Оповещение = Новый ОписаниеОповещения("УдалитьСтрокуЗавершение", ЭтотОбъект);

ПоказатьВопрос(Оповещение, "Удалить выбранную строку?",

РежимДиалогаВопрос.ДаНет, 20, КодВозвратаДиалога.Нет);

КонецПроцедуры

&НаКлиенте

Процедура УдалитьСтрокуЗавершение(Результат, ДополнительныеПараметры) Экспорт

Если Результат = КодВозвратаДиалога.Да Тогда

// логика удаления

КонецЕсли;

КонецПроцедуры

Параметры метода ПоказатьВопрос: описание оповещения, текст вопроса, набор кнопок, таймаут в секундах, кнопка по умолчанию, заголовок окна и кнопка, которая сработает по таймауту. Обязательны только первые два — остальные можно опустить, тогда появится стандартный набор кнопок «ОК».

Обратите внимание на директиву Экспорт в процедуре-обработчике: платформа вызывает её извне модуля формы, поэтому без Экспорт возникнет ошибка «Процедура не обнаружена». Это одна из самых частых причин неработающего вопроса.

Типичные ошибки
01
Нет Экспорт у процедуры-обработчика — платформа не находит процедуру и выдаёт ошибку при ответе пользователя
02
Код продолжает выполняться сразу после ПоказатьВопрос — результат ещё не известен, логика работает с пустым ответом
03
Имя процедуры в ОписаниеОповещения написано с опечаткой — ошибка проявляется только в момент ответа, а не при компиляции
04
Использование Вопрос() в веб-клиенте — вызов завершается ошибкой, так как модальность запрещена

Настройка кнопок диалога через РежимДиалогаВопрос

Набор кнопок определяется системным перечислением РежимДиалогаВопрос. Доступные варианты: ДаНет, ДаНетОтмена, ОК, ОКОтмена, ПовторитьОтмена, ПрерватьПовторитьПропустить. Произвольный текст кнопок задать нельзя — платформа использует стандартные локализованные подписи.

Если нужны кнопки со своими названиями (например, «Сохранить и закрыть», «Не сохранять»), используйте объект СписокЗначений вместо режима диалога: добавьте в него элементы с представлениями, а в качестве значений укажите коды возврата или собственные строковые идентификаторы. В обработчике сравнивайте результат именно с этими значениями.

Кнопка по умолчанию влияет на то, что произойдёт при нажатии Enter. Для деструктивных действий (удаление, отмена проведения) кнопкой по умолчанию всегда делайте безопасный вариант — «Нет» или «Отмена». Это защищает от случайного подтверждения, когда пользователь механически нажимает Enter.

Передача дополнительных параметров в обработчик

Часто логика после ответа зависит от контекста: какую строку удалять, какой документ проводить, какой элемент справочника менять. Эти данные передаются третьим параметром конструктора ОписаниеОповещения — обычно структурой.

&НаКлиенте

Процедура ПометитьНаУдаление(Команда)

Параметры = Новый Структура("СсылкаНаОбъект", ТекущаяСсылка);

Оповещение = Новый ОписаниеОповещения("ПометитьЗавершение", ЭтотОбъект, Параметры);

ПоказатьВопрос(Оповещение, "Пометить объект на удаление?",

РежимДиалогаВопрос.ДаНет, , КодВозвратаДиалога.Нет);

КонецПроцедуры

&НаКлиенте

Процедура ПометитьЗавершение(Результат, ДополнительныеПараметры) Экспорт

Если Результат = КодВозвратаДиалога.Да Тогда

ПометитьНаСервере(ДополнительныеПараметры.СсылкаНаОбъект);

КонецЕсли;

КонецПроцедуры

Важно понимать: между показом вопроса и ответом пользователя состояние формы могло измениться. Пользователь может успеть переключить вкладку, а в длительных сценариях другой сеанс способен изменить объект в базе. Поэтому в обработчике перепроверяйте актуальность данных, а не полагайтесь слепо на значения, захваченные до вопроса.

Таймаут и ответ по умолчанию

Четвёртый параметр ПоказатьВопрос задаёт таймаут в секундах. Если пользователь не ответил за это время, диалог закрывается автоматически, а в обработчик приходит значение, заданное седьмым параметром (кнопка таймаута). Если седьмой параметр не указан, при таймауте возвращается КодВозвратаДиалога.Таймаут.

Таймаут полезен в регламентных сценариях: например, при интерактивном обмене данными, когда отсутствие ответа должно трактоваться как отказ, а не как зависание процесса. Для обычных пользовательских действий таймаут лучше не ставить или ставить достаточно большим — пользователь может отойти от компьютера, и внезапное закрытие диалога с автоматическим «Нет» вызовет недоумение.

Обязательно обрабатывайте значение КодВозвратаДиалога.Таймаут явно, если таймаут задан. Код вида Если Результат = КодВозвратаДиалога.Да Тогда безопасен сам по себе, но если у вас ветвление «иначе — считаем отказом», убедитесь, что таймаут попадает именно в ветку отказа.

Порядок действий
  1. 1
    Создайте процедуру-обработчик с двумя параметрами: Результат и ДополнительныеПараметры, добавьте Экспорт
  2. 2
    Сформируйте ОписаниеОповещения с именем обработчика и нужными дополнительными параметрами
  3. 3
    Вызовите ПоказатьВопрос с текстом, режимом диалога и безопасной кнопкой по умолчанию
  4. 4
    Перенесите всю логику, зависящую от ответа, внутрь процедуры-обработчика
  5. 5
    Проверьте сценарий: ответ Да, ответ Нет, закрытие диалога крестиком, таймаут

Вложенные вопросы и цепочки диалогов

Когда после первого ответа нужно задать уточняющий вопрос, второй ПоказатьВопрос вызывается прямо из обработчика первого. Каждый уровень цепочки требует собственной процедуры-обработчика, что при трёх-четырёх вопросах превращает код в «лесенку» из мелких процедур.

Чтобы цепочка оставалась читаемой, называйте обработчики по смыслу этапа: ПровестиДокументВопросЗавершение, ПровестиДокументПерепроведениеЗавершение. Дополнительные параметры прокидывайте через всю цепочку, добавляя в структуру результаты предыдущих ответов — так финальный обработчик получит полную картину решений пользователя.

Если вопросов больше двух-трёх, подумайте, не заменить ли цепочку одной формой с переключателями. Три последовательных модальных диалога подряд раздражают пользователя сильнее, чем одна форма с тремя опциями и кнопкой «Применить».

Маршрут решения

Как выбрать действие

Нужен простой ответ Да/Нет без контекстаПоказатьВопрос с РежимДиалогаВопрос.ДаНет и обработчиком без дополнительных параметров
Логика зависит от выбранной строки или объектаПередайте ссылку в структуре ДополнительныеПараметры описания оповещения
Нужны нестандартные подписи кнопокИспользуйте СписокЗначений вместо РежимДиалогаВопрос
Подряд идут три и более вопросовЗамените цепочку одной управляемой формой с настройками
Код должен работать в веб-клиентеТолько асинхронный ПоказатьВопрос, модальный Вопрос() исключён

Проверка результата и отладка

Проверять сценарий нужно во всех ветках: положительный ответ, отрицательный, отмена, закрытие диалога крестиком (приходит код кнопки по умолчанию для закрытия либо КодВозвратаДиалога.Отмена) и таймаут, если он задан. Часто разработчики тестируют только ветку «Да», а ошибки в обработке «Нет» всплывают у пользователей.

Если обработчик не вызывается, проверьте три вещи: наличие Экспорт у процедуры, точное совпадение имени процедуры в строке с реальным именем (поиск идёт по строке, опечатки компилятор не ловит) и то, что процедура расположена в том же модуле формы, что и описание оповещения с контекстом ЭтотОбъект.

Для отладки асинхронных вызовов ставьте точку останова внутри обработчика, а не на строке ПоказатьВопрос — после показа диалога управление уходит платформе, и пошаговое исполнение «проваливается» мимо логики ответа.

Контрольные точки

Как проверить результат

Вызов обработчика
Норма

После ответа точка останова в обработчике срабатывает, Результат содержит ожидаемый код

Тревожный признак

Обработчик не вызывается или появляется ошибка «Процедура не обнаружена»

Ветка отказа
Норма

При ответе Нет никакие изменения данных не выполняются

Тревожный признак

Изменения происходят независимо от ответа — код стоит после ПоказатьВопрос, а не в обработчике

Работа в веб-клиенте
Норма

Диалог появляется и ответ обрабатывается корректно

Тревожный признак

Ошибка о запрещённой модальности — где-то остался вызов Вопрос()

Таймаут
Норма

По истечении таймаута в обработчик приходит заданное значение и выполняется безопасная ветка

Тревожный признак

Диалог исчезает, но логика зависает или выполняет деструктивное действие

Часто задаваемые вопросы

Можно ли получить ответ на вопрос сразу, в той же строке кода?

Нет, в асинхронной модели это невозможно принципиально: управление возвращается в код сразу после показа диалога, а ответ приходит позже в отдельную процедуру. Всю зависимую от ответа логику нужно переносить в обработчик оповещения.

Как задать вопрос из серверной процедуры формы?

Напрямую никак — диалоги показываются только на клиенте. Перенесите вызов ПоказатьВопрос в клиентскую процедуру, а серверную логику вызывайте уже из обработчика ответа отдельным серверным методом.

Чем ПоказатьВопрос отличается от ПоказатьПредупреждение?

ПоказатьПредупреждение только информирует пользователя с единственной кнопкой подтверждения и не предполагает выбора. ПоказатьВопрос возвращает код нажатой кнопки и используется, когда от ответа зависит дальнейшая логика.

Почему в обработчик приходит пустое или неожиданное значение?

Чаще всего диалог был закрыт крестиком или по таймауту, а эти случаи не обработаны. Проверяйте результат на равенство конкретному коду возврата (КодВозвратаДиалога.Да), а не на неравенство другому — тогда все нестандартные исходы попадут в безопасную ветку.

Можно ли изменить заголовок окна вопроса?

Да, шестым параметром ПоказатьВопрос передаётся строка заголовка. Если параметр не указан, используется стандартный заголовок конфигурации. Осмысленный заголовок помогает, когда вопрос может появиться на фоне других окон.

Работает ли ПоказатьВопрос в фоновом задании или регламентном?

Нет. Интерактивные диалоги доступны только в интерактивном сеансе на клиенте. В фоновых и регламентных заданиях вместо вопроса нужно закладывать решение в логику: параметризовать поведение или писать предупреждение в журнал регистрации.

Итог

Что важно запомнить

Вопрос в управляемой форме задаётся асинхронно: ПоказатьВопрос + ОписаниеОповещения + экспортная процедура-обработчик. Вся логика, зависящая от ответа, живёт в обработчике. Кнопкой по умолчанию и по таймауту назначайте безопасный вариант, а ветки отказа и закрытия диалога проверяйте явно.