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