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