Разработка и Конфигурация · 10 мин
Как вывести модальное окно в 1С
Как вывести модальное окно в 1С 8.3: методы ПоказатьВопрос, ПоказатьПредупреждение, ОткрытьФормуМодально, блокирующие окна и примеры кода с пояснениями.
Модальное окно в 1С — это диалог, который блокирует работу с остальным интерфейсом до тех пор, пока пользователь не ответит или не закроет его. Такие окна применяются для подтверждения удаления, предупреждений о незаполненных реквизитах, выбора варианта действия и ввода простых значений.
В платформе 1С:Предприятие 8.3 подход к модальности зависит от режима запуска. В режиме такси и при работе через веб-клиент синхронные модальные вызовы (Вопрос, Предупреждение, ОткрытьФормуМодально) либо запрещены, либо требуют специальной настройки, поэтому основным способом стали асинхронные методы с описанием оповещения: ПоказатьВопрос, ПоказатьПредупреждение, ПоказатьВводЗначения.
Ниже разобраны оба подхода: когда допустимы синхронные вызовы, как переписать код на асинхронные методы, как передавать результат обратно в вызывающий код и какие ошибки чаще всего приводят к тому, что окно не открывается или логика «зависает».
Какие виды модальных окон есть в 1С
Практически все задачи сводятся к четырём сценариям: показать информационное сообщение, задать вопрос с вариантами ответа, запросить у пользователя значение и открыть форму выбора или произвольную форму в блокирующем режиме. Для каждого сценария есть по два варианта — устаревший синхронный и рекомендуемый асинхронный.
Отдельный случай — метод ПоказатьОповещениеПользователя. Он не является модальным: окно появляется в углу и не блокирует работу. Его путают с модальными диалогами, но для подтверждений он не подходит, потому что пользователь может проигнорировать сообщение.
Сравнение способов вывода окна
Информационное сообщение с кнопкой ОК. Асинхронный, работает везде, включая веб-клиент.
Подтверждение действия с кнопками Да/Нет и другими. Асинхронный, результат приходит в оповещение.
Синхронные методы. Требуют включённой модальности, не работают в веб-клиенте.
Открытие произвольной формы с блокировкой. Устаревший, заменяется на ОткрытьФорму с РежимОткрытияОкна.БлокироватьОкноВладельца.
Асинхронный вывод вопроса через ПоказатьВопрос
Основной рабочий метод — ПоказатьВопрос. Он принимает описание оповещения (процедуру, которая получит ответ), текст вопроса, набор кнопок и необязательные параметры: таймаут, кнопку по умолчанию, заголовок. Код после вызова продолжает выполняться сразу, а ответ приходит в отдельную процедуру.
&НаКлиенте
Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)
Оповещение = Новый ОписаниеОповещения("ПослеОтветаНаВопрос", ЭтотОбъект);
ПоказатьВопрос(Оповещение, "Записать документ?",
РежимДиалогаВопрос.ДаНет, 20, КодВозвратаДиалога.Нет);
КонецПроцедуры
&НаКлиенте
Процедура ПослеОтветаНаВопрос(Результат, ДополнительныеПараметры) Экспорт
Если Результат = КодВозвратаДиалога.Да Тогда
Записать();
КонецЕсли;
КонецПроцедуры
Процедура обработчика обязательно должна быть объявлена с ключевым словом Экспорт, иначе платформа не сможет её вызвать. Первый параметр обработчика — результат диалога, второй — структура дополнительных параметров, которую можно передать третьим аргументом конструктора ОписаниеОповещения.
Информационное окно и ввод значения
Для простого сообщения используется ПоказатьПредупреждение. Если реакция на закрытие не нужна, первый параметр можно не передавать или указать Неопределено. Параметр «Таймаут» задаёт время в секундах, после которого окно закроется само.
Для запроса значения — ПоказатьВводЗначения, ПоказатьВводЧисла, ПоказатьВводСтроки или ПоказатьВводДаты. Они открывают окно с полем ввода и кнопками ОК/Отмена; если пользователь нажал «Отмена», в обработчик приходит Неопределено, и это нужно проверять.
&НаКлиенте
Процедура ВвестиКоличество(Команда)
Оповещение = Новый ОписаниеОповещения("ПослеВводаЧисла", ЭтотОбъект);
ПоказатьВводЧисла(Оповещение, 1, "Введите количество", 10, 2);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВводаЧисла(Число, ДополнительныеПараметры) Экспорт
Если Число = Неопределено Тогда
Возврат; // пользователь отменил ввод
КонецЕсли;
Количество = Число;
КонецПроцедуры
Открытие формы в блокирующем режиме
Когда стандартных диалогов недостаточно, открывают собственную форму. Современный способ — метод ОткрытьФорму с параметром РежимОткрытияОкна, установленным в БлокироватьОкноВладельца или БлокироватьВесьИнтерфейс. Результат возвращается через описание оповещения, а форма закрывается методом Закрыть(Результат).
&НаКлиенте
Процедура ВыбратьКонтрагента(Команда)
Оповещение = Новый ОписаниеОповещения("ПослеВыбора", ЭтотОбъект);
ОткрытьФорму("Справочник.Контрагенты.ФормаВыбора", , ЭтотОбъект, , , ,
Оповещение, РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
КонецПроцедуры
Устаревший ОткрытьФормуМодально возвращает результат напрямую в точку вызова, но требует включённой модальности в свойствах конфигурации и не работает в веб-клиенте. В новых разработках его применять не следует.
- 1Найдите все вызовы Вопрос(), Предупреждение(), ОткрытьФормуМодально() в модуле
- 2Создайте экспортную процедуру-обработчик с параметрами (Результат, ДополнительныеПараметры)
- 3Замените вызов на ПоказатьВопрос/ПоказатьПредупреждение с ОписаниеОповещения
- 4Перенесите код, зависящий от ответа, внутрь обработчика
- 5Проверьте работу в тонком и веб-клиенте
Настройка модальности в конфигурации
Если требуется поддерживать старый код с синхронными вызовами, в свойствах конфигурации есть параметр «Режим использования модальности». Значение «Использовать» разрешает модальные вызовы, «Не использовать» запрещает их, и тогда Вопрос() вызовет исключение. В типовых конфигурациях режим обычно отключён.
Даже при включённой модальности веб-клиент и мобильная платформа синхронные диалоги не поддерживают. Поэтому включать режим имеет смысл только как временную меру на период постепенного рефакторинга, а не как постоянное решение.
Типичные ошибки и их диагностика
Чаще всего окно «не открывается» по одной из трёх причин: вызов расположен в серверной процедуре (модальные диалоги доступны только на клиенте), у обработчика оповещения отсутствует Экспорт, либо конфигурация запрещает модальность, а код использует синхронный метод.
Вторая группа ошибок — логические: разработчик ожидает, что код после ПоказатьВопрос выполнится после ответа, хотя на самом деле он выполняется сразу. Характерный симптом — документ записывается даже при нажатии «Нет». Лечится переносом зависимой логики в обработчик.
Проверка результата
После внедрения проверьте сценарий во всех клиентах, которые используются в организации: толстый, тонкий и веб-клиент могут вести себя по-разному. Убедитесь, что при каждом варианте ответа (Да, Нет, Отмена, истечение таймаута) выполняется корректная ветка логики.
Как проверить результат
Выполняется целевое действие — запись, удаление, выбор
Ничего не происходит или действие выполняется дважды
Действие отменяется, данные не меняются
Действие выполняется несмотря на отказ
Окно открывается и блокирует интерфейс
Ошибка о недопустимости модального вызова
Что важно запомнить
Используйте асинхронные методы ПоказатьВопрос, ПоказатьПредупреждение и ПоказатьВводЗначения с описанием оповещения; обработчик объявляйте с Экспорт; зависимую от ответа логику размещайте только внутри обработчика; синхронные методы оставляйте лишь для поддержки старого кода.
Частые вопросы
Почему ПоказатьВопрос вызывает ошибку «Использование модальных окон запрещено»?
Эта ошибка относится к синхронному методу Вопрос(), а не к ПоказатьВопрос. Если она появляется, в коде где-то остался старый вызов. Найдите его глобальным поиском по модулю и замените на асинхронный вариант с описанием оповещения.
Как передать в обработчик оповещения свои данные?
Третьим параметром конструктора Новый ОписаниеОповещения передайте произвольное значение — обычно структуру. В обработчике оно придёт вторым параметром (ДополнительныеПараметры). Так удобно передавать, например, ссылку на документ или идентификатор строки таблицы.
Можно ли показать модальное окно из серверной процедуры?
Нет. Диалоги доступны только в клиентском контексте. Если решение принимается на сервере, верните признак на клиент и уже там вызовите ПоказатьВопрос. Либо используйте директиву &НаКлиентеНаСервереБезКонтекста с проверкой, но сам вызов диалога всё равно должен быть в клиентской ветке.
Как сделать, чтобы окно закрылось само через несколько секунд?
У методов ПоказатьВопрос и ПоказатьПредупреждение есть параметр «Таймаут» в секундах. По его истечении диалог закрывается, а в обработчик приходит значение, заданное как кнопка по умолчанию (или КодВозвратаДиалога.Таймаут — поведение зависит от метода, проверяйте в синтакс-помощнике).
Чем заменить ОткрытьФормуМодально для формы выбора?
Используйте ОткрытьФорму с последним параметром РежимОткрытияОкнаФормы.БлокироватьОкноВладельца и описанием оповещения. Для стандартных форм выбора есть ещё проще путь: метод ПоказатьВыборИзСписка или обработчик НачалоВыбора у поля ввода, который сам открывает форму выбора в блокирующем режиме.
Работают ли модальные окна в мобильном клиенте?
Асинхронные методы (ПоказатьВопрос, ПоказатьПредупреждение) в мобильной платформе поддерживаются. Синхронные модальные вызовы — нет. Поэтому при разработке под мобильный клиент асинхронный подход является единственным вариантом.