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