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

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

Что значит «открыть модально» в 1С

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

Фраза «открыть модально» в 1С означает открытие формы (окна) в режиме, при котором пользователь не может работать с остальными окнами программы, пока не закроет это окно. Модальная форма блокирует интерфейс: клики по другим окнам игнорируются, и единственный способ продолжить работу — завершить действие в модальном окне или отменить его.

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

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

Что такое модальное окно и как оно работает

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

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

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

Какие методы открывают формы и диалоги модально

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

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

Типичный фрагмент старого кода выглядит так: вызывается Вопрос("Записать изменения?", РежимДиалогаВопрос.ДаНет), результат сравнивается с КодВозвратаДиалога.Да, и дальше выполняется запись. Вся логика — в одной процедуре, линейно. Именно такой код и перестаёт работать при включённом запрете модальности.

bsl
// Старый модальный вариант
Результат = Вопрос("Записать документ?", РежимДиалогаВопрос.ДаНет);
Если Результат = КодВозвратаДиалога.Да Тогда
    Записать();
КонецЕсли;

Почему платформа запрещает модальность и что использовать вместо неё

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

Асинхронный аналог строится в два шага. Сначала создаётся объект ОписаниеОповещения, в котором указывается имя процедуры-обработчика и, при необходимости, дополнительные параметры. Затем вызывается метод с префиксом «Показать»: ПоказатьВопрос, ПоказатьПредупреждение, ПоказатьВводЗначения. Управление возвращается сразу, а когда пользователь ответит, платформа вызовет указанный обработчик.

bsl
// Современный асинхронный вариант
Оповещение = Новый ОписаниеОповещения("ПослеВопросаОЗаписи", ЭтотОбъект);
ПоказатьВопрос(Оповещение, "Записать документ?", РежимДиалогаВопрос.ДаНет);

&НаКлиенте
Процедура ПослеВопросаОЗаписи(Результат, ДопПараметры) Экспорт
    Если Результат = КодВозвратаДиалога.Да Тогда
        Записать();
    КонецЕсли;
КонецПроцедуры

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

Сравнение подходов

Модальные методы (Вопрос, ОткрытьМодально)

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

Асинхронные методы (ПоказатьВопрос, ОткрытьФорму с оповещением)

Работают во всех клиентах, рекомендованы платформой. Требуют выделения логики продолжения в отдельные процедуры-обработчики.

Блокирующее окно без модальности (БлокироватьОкноВладельца)

Даёт пользователю ощущение модальности, но код остаётся асинхронным. Оптимально для форм выбора и ввода.

Как включить или отключить режим модальности в конфигурации

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

Если вы поддерживаете старую конфигурацию и массовый рефакторинг пока невозможен, временное решение — установить «Использовать с предупреждениями». Модальные вызовы продолжат работать в толстом и тонком клиенте, а в журнал регистрации будут попадать предупреждения, по которым удобно составить список мест для переработки.

Как найти и переработать модальные вызовы в коде

Найти места модальных вызовов помогает встроенная проверка конфигурации (Конфигурация → Проверка конфигурации) с включённым флагом поиска модальных методов, а также глобальный поиск по именам методов: Вопрос(, Предупреждение(, ОткрытьМодально, ВвестиЗначение. Проверка конфигурации надёжнее — она покажет и менее очевидные случаи.

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

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

Типичные ошибки и ограничения

Самая частая ошибка — предположение, что код после ПоказатьВопрос выполнится после ответа пользователя. На самом деле он выполняется немедленно, до ответа. Если после вызова стоит, например, запись объекта, она произойдёт независимо от выбора пользователя. Всё, что зависит от ответа, обязано находиться внутри обработчика оповещения.

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

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

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

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

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

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

Поведение при открытии диалога
Норма

Окно появляется, интерфейс владельца заблокирован, код не падает

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

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

Ответ пользователя
Норма

Ветка логики срабатывает строго по выбранному ответу

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

Действие выполняется до ответа или при любом ответе одинаково

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

Диалоги и формы открываются и возвращают результат

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

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

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

Итог

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

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

Частые вопросы

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

Модальное окно останавливает выполнение кода до своего закрытия и возвращает результат напрямую. Блокирующее окно (режим «БлокироватьОкноВладельца») только запрещает пользователю работать с окном-владельцем, но код продолжает выполняться асинхронно, а результат приходит через оповещение. Визуально для пользователя они почти одинаковы, разница — в модели выполнения.

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

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

Можно ли открыть модально форму выбора и сразу получить выбранное значение?

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

Работают ли модальные вызовы в веб-клиенте?

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

Как передать данные в обработчик оповещения?

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

Что делать, если пользователь закрыл диалог крестиком, а не кнопкой?

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