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