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