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