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