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