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

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

Что такое модальный диалог в 1С и как с ним работать

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

Модальный диалог в 1С — это окно, которое приостанавливает работу пользователя с остальным интерфейсом программы, пока он не ответит на вопрос, не введёт данные или не закроет окно. Классический пример — сообщение «Сохранить изменения?» с кнопками «Да», «Нет» и «Отмена». Пока пользователь не нажмёт одну из кнопок, переключиться на другую форму он не сможет.

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

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

Что такое модальность и чем модальное окно отличается от блокирующего

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

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

Какие модальные диалоги есть в 1С

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

  • Диалог вопроса — выбор из набора кнопок («Да/Нет», «ОК/Отмена», «Повторить/Прервать»). Старый метод — Вопрос(), новый — ПоказатьВопрос().
  • Диалог ввода значения — пользователь вводит число, строку, дату или выбирает элемент справочника. Старый метод — ВвестиЗначение(), новый — ПоказатьВводЗначения().
  • Диалог выбора файла — открытие или сохранение файла. Синхронный вариант не работает в веб-клиенте, используется Показать() у объекта ДиалогВыбораФайла.
  • Предупреждение — информационное окно без ввода данных: ПоказатьПредупреждение().
  • Модальное открытие формы — форма объекта или обработки, открытая с блокировкой владельца: ОткрытьФормуМодально() (устаревший) или ОткрытьФорму() с параметром РежимОткрытияОкна.

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

Почему синхронные модальные вызовы запрещены

Начиная с версии платформы 8.3, в свойствах конфигурации появился параметр «Режим использования модальности». В типовых решениях он установлен в значение «Не использовать». При такой настройке вызов методов Вопрос(), ВвестиЗначение(), ОткрытьФормуМодально() и подобных приводит к ошибке времени выполнения.

Причины отказа от синхронной модальности практические:

  1. Веб-клиент не поддерживает остановку выполнения кода — это ограничение браузерных технологий.
  2. Мобильная платформа работает по той же асинхронной модели.
  3. Синхронные вызовы блокируют интерфейс и мешают параллельной работе, что особенно заметно при медленном соединении.

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

Как правильно показать вопрос пользователю

Современный подход строится на трёх шагах: создать описание оповещения, вызвать асинхронный метод, обработать результат в отдельной процедуре. Код, который раньше шёл после вызова Вопрос(), переносится в обработчик.

&НаКлиенте

Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)

Если Не ПроверкаПройдена Тогда

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

ПоказатьВопрос(Оповещение,

"Проверка не пройдена. Продолжить запись?",

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

Отказ = Истина;

КонецЕсли;

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

&НаКлиенте

Процедура ПослеОтветаНаВопрос(Результат, ДопПараметры) Экспорт

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

Записать();

КонецЕсли;

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

Обратите внимание на важный нюанс: в обработчик события ПередЗаписью нельзя встроить ожидание ответа синхронно. Поэтому типовой приём — отказаться от стандартной записи (Отказ = Истина), задать вопрос, а при положительном ответе вызвать Записать() программно из обработчика оповещения.

Через параметр ДополнительныеПараметры конструктора ОписаниеОповещения в обработчик можно передать любой контекст — ссылку на документ, структуру с данными строки таблицы и т.д. Это заменяет переменные, которые раньше были доступны «естественным образом» в линейном коде.

Перевод старого кода на асинхронный синтаксис
  1. 1
    Найдите синхронный вызов: Вопрос(), ВвестиЗначение(), ОткрытьФормуМодально(), Предупреждение()
  2. 2
    Создайте экспортную клиентскую процедуру-обработчик с параметрами (Результат, ДополнительныеПараметры)
  3. 3
    Перенесите в неё код, который выполнялся после диалога
  4. 4
    Создайте объект ОписаниеОповещения с именем обработчика и контекстом
  5. 5
    Замените вызов на ПоказатьВопрос / ПоказатьВводЗначения / ОткрытьФорму с оповещением о закрытии
  6. 6
    Проверьте работу в тонком клиенте и, если используется, в веб-клиенте

Модальное открытие форм и ввод значений

Для открытия формы с блокировкой родительского окна вместо устаревшего ОткрытьФормуМодально() используется ОткрытьФорму() с двумя дополнительными механизмами: параметр РежимОткрытияОкна в структуре параметров (значение РежимОткрытияОкнаФормы.БлокироватьОкноВладельца) и описание оповещения о закрытии, в которое форма вернёт результат через Закрыть(Результат).

Ввод значения работает аналогично вопросу:

Оповещение = Новый ОписаниеОповещения("ПослеВводаКоличества", ЭтотОбъект);

ПоказатьВводЗначения(Оповещение, 1, "Введите количество", Тип("Число"));

Если пользователь нажмёт «Отмена», в обработчик придёт значение Неопределено — это нужно проверять первым делом, иначе дальнейшая логика упадёт с ошибкой или запишет пустое значение в базу.

Типичные ошибки при работе с модальными диалогами

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

Вторая ошибка — неэкспортная процедура обработчика. Процедура, указанная в описании оповещения, должна быть объявлена с ключевым словом Экспорт, иначе платформа не сможет её вызвать и выдаст ошибку «Процедура не обнаружена».

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

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

Как проверить, что доработка сделана правильно

После перевода кода на асинхронные методы прогоните сценарий минимум в двух клиентах: тонком и веб-клиенте (если база публикуется). Поведение диалогов идентично, но именно в браузере всплывают скрытые синхронные вызовы в смежных участках кода.

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

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

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

Режим использования модальности в свойствах конфигурации
Норма

Не использовать

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

Использовать — синхронные вызовы сломают веб-клиент

Поведение при нажатии «Отмена» в диалоге ввода
Норма

Обработчик получает Неопределено и корректно завершает сценарий

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

Ошибка или запись пустого значения в базу

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

Диалог открывается, результат обрабатывается в оповещении

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

Ошибка времени выполнения или отсутствие реакции на кнопки

Частые вопросы о модальных диалогах в 1С

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

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

Можно ли задать вопрос пользователю из серверной процедуры?

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

Почему возникает ошибка «Использование модальных окон в данном режиме запрещено»?

В свойствах конфигурации режим использования модальности установлен в «Не использовать», а в коде вызывается синхронный метод — Вопрос(), ВвестиЗначение(), ОткрытьФормуМодально() или Предупреждение(). Найдите вызов по тексту ошибки и замените его на асинхронный аналог с описанием оповещения.

Как открыть форму и получить из неё результат без ОткрытьФормуМодально?

Используйте ОткрытьФорму() с параметром РежимОткрытияОкна = БлокироватьОкноВладельца и передайте описание оповещения о закрытии. Открываемая форма возвращает результат через метод Закрыть(Результат), а обработчик оповещения получает его первым параметром.

Что делать, если нужно задать пользователю несколько вопросов подряд?

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

Работает ли Сообщить() как замена модальному предупреждению?

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

Итог

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

Модальный диалог в 1С — окно, требующее ответа пользователя. В платформе 8.3 синхронные методы (Вопрос, ВвестиЗначение) заменены асинхронными (ПоказатьВопрос, ПоказатьВводЗначения) с обработкой результата через ОписаниеОповещения. Диалоги вызываются только на клиенте, обработчик объявляется с Экспорт, а отмену ввода проверяют через Неопределено.