В разработке на платформе 1С:Предприятие 8.3 часто возникает задача динамического изменения интерфейса. Например, когда заранее неизвестно количество элементов, которые должны отобразиться на форме (список групп ученика, перечень активных договоров или доступные подразделения). В этой статье мы подробно разберем, как программно создавать элементы типа Поле надписи, делать их гиперссылками и организовывать переход к формам соответствующих объектов.
Рассмотрим ситуацию: на форме элемента справочника Ученики необходимо вывести список групп, в которых он обучается. Каждая группа должна быть представлена в виде гиперссылки, при нажатии на которую открывается форма этой группы. Типичная ошибка начинающего разработчика заключается в том, что он пытается привязать все созданные элементы к одному и тому же реквизиту, например, к Объект.Ссылка. Это приводит к тому, что при клике на любую созданную надпись система всегда будет открывать форму текущего объекта (самого ученика), а не выбранной группы.
Разберем по шагам, как реализовать эту задачу правильно, учитывая производительность, модель объекта и стандарты разработки 1С.
Прежде чем создавать визуальные элементы, нам нужно получить данные. Важно помнить о производительности: обращение через точку к полям ссылочных типов внутри цикла (например, Выборка.Группа.Наименование) порождает дополнительные неявные запросы к базе данных. Проанализируем, как составить запрос оптимально.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| УченикиВГруппах.Группа КАК Группа,
| УченикиВГруппах.Группа.Наименование КАК ГруппаНаименование
|ИЗ
| РегистрСведений.УченикиВГруппах КАК УченикиВГруппах
|ГДЕ
| УченикиВГруппах.СтатусУченика = &СтатусУченика
| И УченикиВГруппах.Ученик = &Ученик";
Запрос.УстановитьПараметр("СтатусУченика", Перечисления.СтатусУченикаВГруппе.Учится);
Запрос.УстановитьПараметр("Ученик", Объект.Ссылка);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Номер = 1;
Пока Выборка.Следующий() Цикл
СоздатьДинамическийЭлемент(Выборка.Группа, Выборка.ГруппаНаименование, Номер);
Номер = Номер + 1;
КонецЦикла;
КонецПроцедуры
Обратите внимание, что мы сразу получаем ГруппаНаименование в запросе. Это исключает лишнюю нагрузку на сервер при итерации выборки.
Для создания элемента используется метод ЭтаФорма.Элементы.Добавить(). Однако просто добавить элемент мало — нужно определить, как он будет реагировать на действия пользователя. Рассмотрим процесс создания поля надписи, которое ведет себя как гиперссылка.
При программном создании элементов мы столкнемся с тем, что нам нужно где-то хранить ссылку на саму группу, чтобы открыть её позже. Одним из решений является создание динамических реквизитов формы, но для простых задач можно использовать именование элементов или сохранение связей в структуру.
&НаСервере
Процедура СоздатьДинамическийЭлемент(СсылкаНаГруппу, ИмяГруппы, ПорядковыйНомер)
ИмяЭлемента = "Надпись_Группа_" + СтрЗаменить(Строка(СсылкаНаГруппу.УникальныйИдентификатор()), "-", "_");
// Добавляем элемент на форму в определенную группу (контейнер)
НоваяНадпись = Элементы.Добавить(ИмяЭлемента, Тип("ПолеФормы"), Элементы.ГруппаКонтейнер);
НоваяНадпись.Вид = ВидПоляФормы.ПолеНадписи;
НоваяНадпись.Заголовок = ИмяГруппы;
НоваяНадпись.Гиперссылка = Истина;
// Устанавливаем действие при нажатии
НоваяНадпись.УстановитьДействие("Нажатие", "Подключаемый_ПриНажатииНаГруппу");
// Чтобы на клиенте понять, какую ссылку открывать, можно использовать
// скрытые реквизиты или соответствие, но самый простой способ —
// связать элемент с данными, если вы заранее создали реквизиты.
КонецПроцедуры
Теперь разберем, как реализовать обработчик нажатия на клиенте. Основная сложность здесь — передать ссылку на объект из сервера на клиент. Если мы создавали динамические реквизиты через ИзменитьРеквизиты(), мы можем просто обратиться к ним. Если же нет, мы можем использовать параметры самого элемента или вспомогательную коллекцию.
Рассмотрим универсальный способ открытия формы объекта по ссылке:
&НаКлиенте
Процедура Подключаемый_ПриНажатииНаГруппу(Элемент)
// В реальной задаче ссылку можно получить из соответствия имен элементов и ссылок,
// подготовленного на сервере при создании элементов.
// Допустим, мы получили СсылкаНаОбъект.
ПараметрыФормы = Новый Структура("Ключ", СсылкаНаОбъект);
ОткрытьФорму("Справочник.Группы.ФормаОбъекта", ПараметрыФормы);
КонецПроцедуры
Использование параметра Ключ в структуре параметров формы — это стандартный механизм платформы 1С для открытия существующего элемента объекта. Если передать Ключ, система поймет, что нужно открыть не новую форму, а форму конкретной записи базы данных.
Создание множества отдельных элементов ПолеФормы может замедлить работу интерфейса, если групп слишком много. Проанализируем более эффективный подход — использование одного реквизита типа ФорматированнаяСтрока. Этот объект позволяет внедрять гиперссылки прямо в текст, причем в качестве значения гиперссылки можно передать саму ссылку на объект.
Выясним преимущества этого метода:
ОткрытьФорму.Пример реализации через форматированную строку:
&НаСервере
Процедура ЗаполнитьСписокГруппФорматированнойСтрокой()
МассивЭлементов = Новый Массив;
// Допустим, мы получили данные запросом
Пока Выборка.Следующий() Цикл
Если МассивЭлементов.Количество() > 0 Тогда
МассивЭлементов.Добавить(", "); // Разделитель
КонецЕсли;
// Создаем гиперссылку, где значением является сама ссылка на группу
МассивЭлементов.Добавить(Новый ФорматированнаяСтрока(Выборка.ГруппаНаименование, , , , Выборка.Группа));
КонецЦикла;
// ГруппыТекст - это реквизит формы с типом ФорматированнаяСтрока
ГруппыТекст = Новый ФорматированнаяСтрока(МассивЭлементов);
КонецПроцедуры
Разберем ситуацию, когда данные ученика изменились или форма обновилась. Если мы просто будем добавлять элементы в цикле, при каждом вызове процедуры система будет пытаться создать элементы с теми же именами, что приведет к ошибке.
Обязательно перед циклом создания элементов нужно реализовать процедуру очистки:
&НаСервере
Процедура ОчиститьДинамическиеЭлементы()
МассивДляУдаления = Новый Массив;
Для Каждого Элемент Из Элементы.ГруппаКонтейнер.ПодчиненныеЭлементы Цикл
МассивДляУдаления.Добавить(Элемент);
КонецЦикла;
Для Каждого Элемент Из МассивДляУдаления Цикл
Элементы.Удалить(Элемент);
КонецЦикла;
КонецПроцедуры
Посмотрим на этот процесс внимательно: мы сначала собираем элементы в массив, а потом удаляем их. Это необходимо, так как удаление элемента напрямую из коллекции во время обхода этой же коллекции через Для Каждого может привести к ошибкам и пропуску элементов.
Мы рассмотрели два основных способа решения задачи. Первый — через программное добавление элементов ПолеФормы — дает максимальную гибкость, позволяя настраивать обработчики событий и передавать сложные параметры. Второй — через ФорматированнаяСтрока — является более легким и предпочтительным для простого отображения списков ссылок. Выбор метода зависит от требований к интерфейсу и сложности логики, которую необходимо выполнить при нажатии на элемент.