Разработчики при создании сложных и эргономичных интерфейсов в системе «1С:Предприятие 8.3» часто сталкиваются с задачей размещения одной формы внутри другой. Это может быть необходимо для создания дашбордов, многошаговых мастеров (визардов), сложных рабочих мест или интерактивных панелей управления. Однако стандартная архитектура управляемого приложения накладывает жесткие ограничения на такое поведение интерфейса. Разберем детально, почему возникает эта сложность и как её можно элегантно решить с помощью различных обходных технологий.
Попытка вызвать стандартный метод ОткрытьФорму с указанием родительского окна в качестве контейнера часто приводит к тому, что дочернее окно просто заменяет содержимое материнского окна или открывается в отдельной вкладке. Давайте проанализируем синтаксис системного метода:
ОткрытьФорму(ИмяФормы, Параметры, Владелец, Уникальность, Окно, ...)
Параметр Окно принимает значение типа ОкноКлиентскогоПриложения. В управляемом приложении этим окном может быть либо основное окно программы, либо вспомогательное всплывающее окно. Платформа 1С спроектирована по принципу разделения контекстов, поэтому буквально «внедрить» одну форму в область (группу) другой формы стандартным вызовом метода невозможно. Попытка передать туда ЭтаФорма.Окно приводит к замещению текущего содержимого.
Тем не менее, существует несколько проверенных способов решения этой задачи разного уровня сложности. Рассмотрим их по шагам.
Если нам необходимо отобразить данные и элементы управления другой формы, мы можем воссоздать её структуру динамически. Этот метод наиболее близок к концепции «внедрения» формы.
Алгоритм реализации:
СправочникОбъект.Номенклатура или произвольная таблица значений).ПолучитьФорму() на сервере (без её фактического открытия на клиенте), мы можем прочитать структуру элементов метаданных исходной формы.Элементы.Добавить() создаем аналогичные элементы в целевой группе основной формы.ПутьКДанным.Рассмотрим пример программного добавления реквизитов и элементов на сервере:
&НаСервере
Процедура ВнедритьЭлементыФормыНаСервере()
// Шаг 1. Добавляем новый реквизит на форму программно
МассивДобавляемыхРеквизитов = Новый Массив;
ТипРеквизита = Новый ОписаниеТипов("СправочникСсылка.Номенклатура");
НовыйРеквизит = Новый РеквизитФормы("ВнедренныйТовар", ТипРеквизита, "", "Выбранный товар");
МассивДобавляемыхРеквизитов.Добавить(НовыйРеквизит);
// Применяем изменения к структуре формы
ИзменитьРеквизиты(МассивДобавляемыхРеквизитов);
// Шаг 2. Создаем контейнер (группу) для размещения элементов
ГруппаКонтейнер = Элементы.Добавить("ГруппаПодформа", Тип("ГруппаФормы"), ЭтаФорма);
ГруппаКонтейнер.Вид = ВидГруппыФормы.ОбычнаяГруппа;
ГруппаКонтейнер.Заголовок = "Свойства внедренного объекта";
// Шаг 3. Создаем элементы управления
НовоеПоле = Элементы.Добавить("ПолеТовара", Тип("ПолеФормы"), ГруппаКонтейнер);
НовоеПоле.Вид = ВидПоляФормы.ПолеВвода;
НовоеПоле.ПутьКДанным = "ВнедренныйТовар";
КонецПроцедуры
Этот способ требует написания дополнительного кода для синхронизации данных, но обеспечивает бесшовную интеграцию интерфейса.
Вместо того чтобы динамически создавать элементы во время работы программы, гораздо надежнее спроектировать их заранее на этапе разработки в конфигураторе. Мы можем объединить несколько логических блоков (подформ) внутри одной физической формы.
Для этого мы используем элементы типа Группа - Страницы или обычные группы с управляемой видимостью. Разберем этот процесс по шагам:
Посмотрим на пример кода, переключающего подформы по нажатию кнопок:
&НаКлиенте
Процедура ПереключитьРазделИнтерфейса(ИмяРаздела)
// Переключаем видимость страниц программно
Если ИмяРаздела = "Продажи" Тогда
Элементы.СтраницаПродажи.Видимость = Истина;
Элементы.СтраницаЗакупки.Видимость = Ложь;
ИначеЕсли ИмяРаздела = "Закупки" Тогда
Элементы.СтраницаПродажи.Видимость = Ложь;
Элементы.СтраницаЗакупки.Видимость = Истина;
КонецЕсли;
КонецПроцедуры
Преимущество метода: Высокая скорость работы, отсутствие сложного программного кода генерации элементов, простота поддержки интерфейса в конфигураторе.
Если требуется вывести сложный интерактивный интерфейс, веб-приложение или динамическую инфографику, лучшим решением будет использование элемента формы Поле HTML-документа.
Этот механизм позволяет транслировать сверстанный HTML-код непосредственно внутрь управляемой формы 1С. Мы можем организовать полноценный двусторонний обмен данными между платформой 1С и JavaScript-кодом внутри HTML-страницы.
Разберем пример инициализации HTML-поля:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Формируем простой HTML-интерфейс
ТекстHTML = "
|<html>
|<head>
| <style>
| body { font-family: Arial, sans-serif; background-color: #f0f0f0; padding: 10px; }
| .card { background: white; padding: 15px; border-radius: 5px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); }
| <s/tyle>
|</head>
|<body>
| <div class='card'>
| <h3>Информационная панель</h3>
| <p>Данные загружены из базы 1С.</p>
| <button onclick='window.external.OnClickButton(""НажатаКнопка"")'>Взаимодействие с 1С</button>
| </div>
|</body>
|</html>";
ЭтаФорма.СодержимоеHTML = ТекстHTML;
КонецПроцедуры
Для обработки кликов по кнопкам внутри HTML-документа используем событие ПриНажатии у элемента формы ПолеHTMLДокумента. В обработчике мы можем получить переданные параметры и выполнить необходимый код на стороне 1С.
Начиная с версии платформы 8.3.15, разработчикам стал доступен встроенный механизм создания информационных панелей. Этот инструмент разработан специально для компоновки различных отчетов, графиков и списков в единой рабочей области.
Этот метод отлично подходит для аналитических задач. Информационная панель позволяет объединять несколько независимых форм отчетов, динамически перестраивать их макет и выводить на один экран без написания сложного программного кода.
Если вашей целью является не столько визуальное встраивание одной формы в другую, сколько обеспечение строгой последовательности ввода данных и логической связи между ними, используйте параметры блокировки интерфейса.
При вызове подчиненной формы передавайте параметр РежимОткрытияОкнаФормы.БлокироватьОкноВладельца. В этом случае дочернее окно визуально позиционируется поверх родительского и не позволяет пользователю вернуться к работе с основной формой до тех пор, пока подчиненная форма не будет закрыта.
&НаКлиенте
ПроцедураОткрытьПодчиненнуюФорму()
ПараметрыОткрытия = Новый Структура;
ПараметрыОткрытия.Вставить("Ключ", ТекущийДокумент);
// Блокируем окно владельца для жесткой связи контекстов
ОткрытьФорму(
"Документ.РеализацияТоваровУслуг.Форма.ФормаДокумента",
ПараметрыОткрытия,
ЭтаФорма,
Истина,
,
,
,
РежимОткрытияОкнаФормы.БлокироватьОкноВладельца
);
КонецПроцедуры
Несмотря на то, что прямое открытие управляемой формы внутри другой формы заблокировано на уровне архитектуры платформы «1С:Предприятие 8.3», мы располагаем широким набором инструментов для обхода этого ограничения. Выбор конкретного метода зависит от архитектурных задач: