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