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