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