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