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