Как программно передать данные в ДополнительныеСвойства объекта при открытии формы на клиенте

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В практике разработки на платформе 1С:Предприятие 8.3 часто возникает ситуация, когда необходимо передать специфическую информацию из одной формы (например, обработки) в другую (форму нового элемента справочника). Особую сложность представляет задача записи этих данных в коллекцию ДополнительныеСвойства прикладного объекта. Сложность заключается в том, что сама форма на клиенте оперирует типом ДанныеФормыСтруктура, у которого нет доступа к этой коллекции, а ДополнительныеСвойства существуют только у серверного объекта (СправочникОбъект, ДокументОбъект и т.д.).

В данной статье мы подробно разберем, как преодолеть этот разрыв между клиентом и сервером, проанализируем различные подходы и выберем наиболее оптимальный вариант, который позволит избежать дублирования кода в множестве форм.

Постановка задачи и анализ ограничений

Представим ситуацию: вы программно открываете форму нового элемента справочника с клиента. Вам нужно передать туда некий «флаг» или структуру данных, которую должна прочитать подписка на событие ПередЗаписью этого справочника. Напрямую обратиться к Форма.Объект.ДополнительныеСвойства на клиенте нельзя — такого свойства просто не существует в данных формы.

Многие разработчики пытаются использовать метод РеквизитФормыВЗначение("Объект"), но он доступен только в серверном контексте формы. Если же мы находимся на клиенте в момент вызова ОткрытьФорму, мы не можем «заглянуть» внутрь будущего объекта. Рассмотрим, как правильно выстроить цепочку передачи данных.

Метод 1. Использование параметров формы и события ПередЗаписьюНаСервере

Этот метод является наиболее надежным и стандартным. Идея заключается в том, чтобы передать данные в параметрах открытия формы, временно сохранить их в реквизите формы, а затем при записи переложить в объект.

Разберем процесс по шагам:

  1. Передача данных при открытии: При вызове формы передаем структуру параметров.

// Код в исходной обработке на клиенте
ПараметрыОткрытия = Новый Структура;
ПараметрыОткрытия.Вставить("МоиСлужебныеДанные", СтруктураСДанными);
ОткрытьФорму("Справочник.Номенклатура.ФормаОбъекта", ПараметрыОткрытия);
  1. Прием данных на сервере формы: В модуле открываемой формы в событии ПриСозданииНаСервере мы считываем эти параметры. Чтобы не потерять их при последующих серверных вызовах, их стоит сохранить либо в скрытый реквизит формы, либо в переменную модуля формы (если используется только один серверный вызов).
  2. Перенос в ДополнительныеСвойства: Самый важный этап происходит в событии ПередЗаписьюНаСервере. В этом обработчике доступен параметр ТекущийОбъект, который имеет тип прикладного объекта.

&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
    // Извлекаем данные, которые мы сохранили при создании формы
    Если СлужебныеДанные <> Неопределено Тогда
        ТекущийОбъект.ДополнительныеСвойства.Вставить("ДанныеИзФормы", СлужебныеДанные);
    КонецЕсли;
КонецПроцедуры

Важный нюанс: Коллекция ДополнительныеСвойства объекта ТекущийОбъект в этом событии — это именно те свойства, которые «поедут» дальше в модуль объекта и в подписки на события. Это идеальное место для их инициализации.

Метод 2. Использование параметра ЗначенияЗаполнения (для новых объектов)

Если задача стоит именно в передаче данных для нового объекта, мы можем использовать встроенный механизм платформы ЗначенияЗаполнения. Платформа автоматически транслирует этот параметр в обработчик модуля объекта ОбработкаЗаполнения.

Проанализируем этот путь:

  1. При открытии формы передаем параметр ЗначенияЗаполнения.

ПараметрыОткрытия = Новый Структура;
ДанныеЗаполнения = Новый Структура("КлючСлужебный", "ЗначениеСлужебное");
ПараметрыОткрытия.Вставить("ЗначенияЗаполнения", ДанныеЗаполнения);
ОткрытьФорму("Справочник.Контрагенты.ФормаОбъекта", ПараметрыОткрытия);
  1. В модуле объекта (не формы!) прописываем логику:

Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
    Если ТипЗнч(ДанныеЗаполнения) = Тип("Структура") 
        И ДанныеЗаполнения.Свойство("КлючСлужебный") Тогда
        ДополнительныеСвойства.Вставить("КлючСлужебный", ДанныеЗаполнения.КлючСлужебный);
    КонецЕсли;
КонецПроцедуры

Этот способ позволяет избежать написания кода в модуле каждой формы, так как логика сосредоточена в модуле самого объекта. Однако помните, что ДополнительныеСвойства живут только в рамках текущего серверного вызова. Если пользователь откроет форму, посидит в ней 10 минут и нажмет «Записать», коллекция к этому моменту может быть уже пуста, так как объект пересоздается при каждом обращении к серверу из формы.

Метод 3. Оптимизация для множества форм (Общие модули и Расширения)

Как справедливо заметили участники обсуждения, если объектов много (десятки справочников), прописывать в каждой форме обработчик ПередЗаписьюНаСервере — это трудозатратно и неудобно в поддержке. Чтобы оптимизировать процесс, рассмотрим два подхода:

  1. Универсальный вызов в общем модуле: В каждой форме вы пишите всего одну строку кода, вызывающую процедуру из общего модуля.
    
    &НаСервере
    Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
        СлужебныйМодуль.ЗаполнитьДопСвойстваИзПараметровФормы(ТекущийОбъект, Параметры);
    КонецПроцедуры
    
  2. Использование расширений: Это самый современный метод. Вы можете создать расширение и добавить в него обработку события ПередЗаписьюНаСервере сразу для всех нужных форм через механизм аннотаций &После. Это позволит централизованно управлять логикой, не изменяя основную конфигурацию.

Метод 4. Работа через ПриЧтенииНаСервере

Если вы работаете с уже существующим объектом, обратите внимание на событие ПриЧтенииНаСервере. Оно также предоставляет доступ к ТекущийОбъект. Рассмотрим ситуацию, когда данные нужно пробросить сразу после открытия формы существующего элемента. В этом событии вы можете прочитать данные из параметров формы и поместить их в ДополнительныеСвойства объекта, чтобы они были доступны при последующих действиях в рамках этого серверного вызова.

Почему нельзя просто «написать в реквизит формы»?

Многие новички путают реквизиты формы и свойства объекта. Нужно четко понимать: ДополнительныеСвойства — это временная структура в оперативной памяти сервера, привязанная к конкретному экземпляру объекта. Она не сохраняется в базе данных и не передается на клиент. Любое изменение в форме на клиенте никак не влияет на ДополнительныеСвойства, пока вы явно не инициируете серверный вызов и не переложите данные программно.

Выясним причину потери данных: если вы записали что-то в ДополнительныеСвойства в процедуре ПриСозданииНаСервере, а потом форма просто открылась и ждет действий пользователя — при нажатии кнопки «Записать» будет создан новый серверный контекст, и старые ДополнительныеСвойства будут утеряны. Именно поэтому заполнять их нужно непосредственно в момент записи — в ПередЗаписьюНаСервере.

Резюме

Мы проанализировали проблему программного доступа к ДополнительнымСвойствам и пришли к следующим выводам:

Используя эти подходы, вы сможете гибко управлять поведением системы и передавать любые служебные данные в подписки на события, обеспечивая чистоту и надежность кода вашей конфигурации.

← На главную