В процессе разработки или обновления конфигураций на платформе 1С:Предприятие 8.3 многие программисты сталкиваются с критической ошибкой: Использование модальных окон запрещено. Эта проблема особенно актуальна при переходе с обычных форм на управляемые или при попытке запустить старый код в веб-клиенте. Рассмотрим подробнее, почему возникло это ограничение, и разберем по шагам, как переписать код так, чтобы он соответствовал современным стандартам платформы.
Причина кроется в архитектурных изменениях платформы. Модальные окна (такие как Вопрос(), Предупреждение(), ОткрытьФормуМодально()) полностью блокируют работу всего приложения и всех его вкладок до тех пор, пока пользователь не закроет окно. В современных браузерах и веб-технологиях такая блокировка считается плохой практикой и часто блокируется самими браузерами.
Для обеспечения стабильной работы в веб-клиенте и повышения отзывчивости интерфейса, компания «1С» ввела запрет на модальность. Проанализируем ситуацию: если в свойствах вашей конфигурации параметр Режим использования модальности установлен в значение Не использовать, любой вызов модального метода приведет к аварийному завершению процедуры. Нам необходимо перевести интерфейсные взаимодействия в асинхронный режим.
Прежде чем приступать к написанию кода, проверим настройки самой базы. Если вы занимаетесь глубокой реструктуризацией старой системы, у вас есть два пути:
Использовать. Это позволит старому коду работать, но сделает невозможной полноценную работу в браузере.Не использовать и внедрить механизм Описания оповещений. Это обеспечит кроссплатформенность и готовность к работе в облачных сервисах.Ключевым объектом для замены модальности является ОписаниеОповещения. Посмотрим на его структуру. Этот объект указывает платформе, какую процедуру нужно выполнить после того, как пользователь совершит действие в диалоговом окне (нажмет кнопку, выберет файл и т.д.).
Конструктор объекта выглядит следующим образом:
Новый ОписаниеОповещения("<ИмяПроцедуры>", <Модуль>, <ДополнительныеПараметры>);
Где <ИмяПроцедуры> — это строка с названием экспортной процедуры, которая примет результат выбора пользователя.
Рассмотрим пример. Раньше мы писали синхронный код, который ждал ответа пользователя прямо в месте вызова:
Ответ = Вопрос("Продолжить выполнение операции?", РежимДиалога.ДаНет);
Если Ответ = КодВозвратаДиалога.Да Тогда
// Основная логика
КонецЕсли;
В новом режиме работы нам нужно разделить этот алгоритм на две части. Проанализируем новый подход:
Шаг 1: Вызов диалога
&НаКлиенте
Процедура НачатьВыполнениеОперации(Команда)
Оповещение = Новый ОписаниеОповещения("ЗавершитьВыполнениеОперации", ЭтотОбъект);
ПоказатьВопрос(Оповещение, "Продолжить выполнение операции?", РежимДиалога.ДаНет);
КонецПроцедуры
Шаг 2: Обработка результата в отдельной процедуре
&НаКлиенте
Процедура ЗавершитьВыполнениеОперации(Результат, ДополнительныеПараметры) Экспорт
Если Результат = КодВозвратаДиалога.Да Тогда
// Продолжаем логику, которая раньше шла сразу после Вопрос()
Сообщить("Пользователь согласился.");
КонецЕсли;
КонецПроцедуры
Работа с формами также претерпела изменения. Вместо блокирующего вызова ОткрытьФормуМодально() мы должны использовать ОткрытьФорму() с передачей описания оповещения о закрытии.
Посмотрим на пример открытия формы подбора товаров:
&НаКлиенте
Процедура ВыбратьТовары(Команда)
ПараметрыОповещения = Новый ОписаниеОповещения("ПослеПодбораТоваров", ЭтотОбъект);
ОткрытьФорму("Справочник.Номенклатура.ФормаВыбора", , ЭтаФорма, , , , ПараметрыОповещения);
КонецПроцедуры
&НаКлиенте
Процедура ПослеПодбораТоваров(РезультатВыбора, ДополнительныеПараметры) Экспорт
Если ЗначениеЗаполнено(РезультатВыбора) Тогда
// Обработка выбранного элемента
Сообщить("Выбран товар: " + РезультатВыбора);
КонецЕсли;
КонецПроцедуры
Часто в процедуру обработки результата (callback) нужно передать контекст — данные, которые были доступны в исходной процедуре. Для этого используется третий параметр конструктора ОписаниеОповещения.
Разберем ситуацию, когда нам нужно передать структуру данных:
&НаКлиенте
Процедура ПроверитьСтатус(Команда)
Контекст = Новый Структура;
Контекст.Вставить("ИмяТекущегоОбъекта", "ДокументПродажи");
Контекст.Вставить("ДатаНачала", ТекущаяДата());
Оповещение = Новый ОписаниеОповещения("ОбработатьОтветСтатуса", ЭтотОбъект, Контекст);
ПоказатьВопрос(Оповещение, "Изменить статус?", РежимДиалога.ОКОтмена);
КонецПроцедуры
&НаКлиенте
Процедура ОбработатьОтветСтатуса(Результат, ДополнительныеПараметры) Экспорт
// ДополнительныеПараметры теперь содержат нашу структуру
Если Результат = КодВозвратаДиалога.ОК Тогда
Сообщить("Работаем с объектом: " + ДополнительныеПараметры.ИмяТекущегоОбъекта);
КонецЕсли;
КонецПроцедуры
Проанализируем ключевые моменты, которые нужно учитывать, чтобы избежать логических ошибок при отказе от модальности:
Экспорт, иначе платформа не сможет его вызвать из контекста диалогового окна.ПоказатьВопрос() код основной процедуры продолжит выполняться сразу, не дожидаясь ответа пользователя. Поэтому всю логику, зависящую от выбора, обязательно нужно переносить в процедуру оповещения.Рассмотрим распространенные ошибки программистов 1С:
&НаКлиенте. Сервер не может напрямую взаимодействовать с интерактивными окнами пользователя.ДополнительныеПараметры, в процедуре оповещения они будут недоступны, так как стек вызовов основной процедуры уже будет завершен.Для или Для Каждого, если вы хотите "остановить" цикл до ответа. В таких случаях цикл нужно реализовывать через рекурсивный вызов процедур оповещения.Подведем итог: переход от модальности к асинхронности требует изменения архитектурного мышления. Вместо линейного кода мы строим событийно-ориентированную модель. Использование объектов ОписаниеОповещения и методов семейства Показать... (например, ПоказатьПредупреждение, ПоказатьВводЗначения) делает вашу конфигурацию современной, быстрой и совместимой со всеми вариантами клиентских приложений 1С.