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