К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как программно добавить событие элемента формы в 1С

Как программно добавить обработчик события элемента формы в 1С: УстановитьДействие, динамическое создание элементов, примеры кода и типичные ошибки.

В управляемых формах 1С события элементов обычно назначаются в конфигураторе через палитру свойств. Но когда элементы создаются динамически — например, кнопки, поля и колонки таблицы, добавляемые кодом в зависимости от данных, — назначить обработчик можно только программно. Для этого используется метод УстановитьДействие(), который связывает событие элемента формы с процедурой модуля формы.

Программное назначение событий требуется в типовых сценариях: динамическое построение интерфейса настроек, добавление кнопок в командную панель при определённых условиях, создание полей для дополнительных реквизитов, программная доработка форм через механизм расширений. Во всех этих случаях элемент появляется в форме только в момент выполнения, и конфигуратор «не знает» о его существовании.

Важно понимать ограничение механизма: метод УстановитьДействие() работает только на сервере или в контексте формы, а процедура-обработчик должна существовать в модуле формы заранее — создать её динамически нельзя. Поэтому типовой подход — заранее объявить универсальные процедуры-обработчики и назначать их динамически создаваемым элементам.

Как устроен механизм событий элементов формы

Каждый элемент управляемой формы (кнопка, поле ввода, таблица, декорация) поддерживает набор событий: Нажатие, ПриИзменении, НачалоВыбора, ОбработкаВыбора, ПриАктивизацииСтроки и другие. В конфигураторе эти события привязываются к процедурам модуля формы через свойства элемента, и платформа сама формирует связку «элемент — событие — обработчик».

При программном создании элемента эта связка отсутствует: элемент отображается, но никак не реагирует на действия пользователя. Метод УстановитьДействие() восполняет этот пробел — он принимает имя события строкой и имя процедуры из модуля формы. Сигнатура процедуры должна соответствовать событию: например, для Нажатие у кнопки это процедура без параметров, а для ПриИзменении поля — процедура с параметром Элемент.

Базовый пример: кнопка с обработчиком нажатия

Рассмотрим минимальный рабочий сценарий: в форме документа нужно программно добавить кнопку в командную панель и назначить ей обработчик. Сначала создаётся команда формы (для кнопок обязателен именно механизм команд), затем элемент-кнопка, затем назначается действие.

&НаСервере

Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

// 1. Добавляем команду формы

Команда = Команды.Добавить("ЗаполнитьПоУмолчанию");

Команда.Заголовок = "Заполнить по умолчанию";

Команда.Действие = "Подключаемый_ЗаполнитьПоУмолчанию";

// 2. Добавляем кнопку в командную панель формы

Кнопка = Элементы.Добавить("КнопкаЗаполнить", Тип("КнопкаФормы"),

Элементы.КоманднаяПанель);

Кнопка.ИмяКоманды = "ЗаполнитьПоУмолчанию";

КонецПроцедуры

&НаКлиенте

Процедура Подключаемый_ЗаполнитьПоУмолчанию(Команда)

ЗаполнитьПоУмолчаниюНаСервере();

КонецПроцедуры

Для кнопок действие назначается через свойство Действие команды, а не через УстановитьДействие() — это важная особенность. А вот для полей ввода, таблиц и прочих элементов, у которых нет привязки к командам, используется именно УстановитьДействие().

bsl
Элементы.Добавить("ПолеКомментарий", Тип("ПолеФормы"), Элементы.ГруппаДанные);
Элементы.ПолеКомментарий.ПутьКДанным = "Объект.Комментарий";
Элементы.ПолеКомментарий.УстановитьДействие("ПриИзменении", "Подключаемый_КомментарийПриИзменении");

Назначение событий полям ввода и таблицам

Поле ввода, созданное программно, требует привязки к данным формы через свойство ПутьКДанным, иначе оно не сможет ни отображать, ни сохранять значение. После привязки назначаются нужные события. Чаще всего используются ПриИзменении, НачалоВыбора и Очистка.

&НаСервере

Процедура ДобавитьПолеКонтрагента()

Поле = Элементы.Добавить("ПолеКонтрагент", Тип("ПолеФормы"),

Элементы.ГруппаРеквизиты);

Поле.ПутьКДанным = "Объект.Контрагент";

Поле.Вид = ВидПоляФормы.ПолеВвода;

Поле.УстановитьДействие("ПриИзменении",

"Подключаемый_КонтрагентПриИзменении");

Поле.УстановитьДействие("НачалоВыбора",

"Подключаемый_КонтрагентНачалоВыбора");

КонецПроцедуры

&НаКлиенте

Процедура Подключаемый_КонтрагентПриИзменении(Элемент)

// Реакция на изменение значения

КонецПроцедуры

Для таблиц формы (элемент типа «ТаблицаФормы») события назначаются аналогично: ПриАктивизацииСтроки, ПередУдалением, ПриНачалеРедактирования. Обратите внимание, что сигнатуры обработчиков различаются: ПередУдалением требует параметры Элемент и Отказ, а ПриАктивизацииСтроки — только Элемент. Несовпадение сигнатуры приведёт к ошибке выполнения при наступлении события.

Один обработчик для нескольких элементов

Когда динамически создаётся множество однотипных элементов — например, набор полей по списку дополнительных реквизитов — назначать каждому отдельную процедуру нерационально. Вместо этого всем элементам назначается один обработчик, а внутри него элемент различается по имени через параметр Элемент.Имя.

&НаКлиенте

Процедура Подключаемый_ДопРеквизитПриИзменении(Элемент)

ИмяРеквизита = СтрЗаменить(Элемент.Имя, "ДопРеквизит_", "");

// Дальнейшая обработка по имени реквизита

КонецПроцедуры

Рекомендуется формировать имена динамических элементов по шаблону с префиксом и ключом: ДопРеквизит_Артикул, Кнопка_Печать_Счет. Это позволяет в общем обработчике однозначно извлечь контекст и не плодить десятки однотипных процедур. Префикс Подключаемый_ в именах процедур — распространённое соглашение, упрощающее поиск таких обработчиков в модуле.

Порядок добавления события элементу
  1. 1
    Объявите в модуле формы процедуру-обработчик с корректной сигнатурой для нужного события
  2. 2
    Создайте элемент методом Элементы.Добавить() с указанием типа и родителя
  3. 3
    Заполните обязательные свойства: ПутьКДанным для полей, ИмяКоманды для кнопок
  4. 4
    Назначьте событие методом УстановитьДействие(ИмяСобытия, ИмяПроцедуры)
  5. 5
    Откройте форму в режиме предприятия и проверьте срабатывание обработчика

Где размещать код назначения событий

Динамическое создание элементов и назначение событий выполняется на сервере — клиентский контекст для этого недоступен. Стандартное место — обработчик ПриСозданииНаСервере, если состав элементов известен при открытии формы. Если элементы зависят от действий пользователя, код выносится в отдельную серверную процедуру, вызываемую из клиентского обработчика.

Учтите, что при серверных вызовах форма пересоздаётся на сервере, и динамически добавленные элементы могут быть утрачены, если логика их создания не выполняется повторно. Надёжный приём — вынести построение динамических элементов в отдельную процедуру и вызывать её как из ПриСозданииНаСервере, так и после действий, меняющих состав элементов.

Типичные ошибки и их диагностика

Самая частая проблема — событие назначено, но обработчик не вызывается. Причины: процедура объявлена с директивой &НаСервере, тогда как событие интерактивное и требует клиентского контекста; имя процедуры указано с опечаткой; процедура объявлена после того, как форма уже построена, но назначение выполнено до её объявления в другом модуле — последнее невозможно, процедура обязана быть в модуле той же формы.

Вторая группа ошибок — неверная сигнатура обработчика. Платформа при срабатывании события выдаёт сообщение о несоответствии параметров. Лечится сверкой с сигнатурой из синтакс-помощника. Третья типичная ситуация — попытка назначить действие кнопке через УстановитьДействие("Нажатие", ...): для кнопок формы обработчик задаётся через команду, а не напрямую.

Типичные ошибки
01
Обработчик объявлен с &НаСервере для интерактивного события — событие не срабатывает или падает с ошибкой контекста
02
Назначение Нажатие кнопке через УстановитьДействие вместо свойства Действие команды — кнопка остаётся неактивной
03
Отсутствует привязка ПутьКДанным у поля ввода — поле отображается, но не хранит значение
04
Опечатка в имени процедуры в УстановитьДействие — ошибка проявляется только при наступлении события
05
Несовпадение сигнатуры обработчика с требуемой для события — ошибка выполнения в момент действия пользователя

Проверка результата и альтернативы

После внедрения кода проверьте три вещи: элемент появляется в форме в нужном родителе и с корректным представлением; событие срабатывает при действии пользователя (поставьте точку останова в обработчике); данные, связанные с элементом, корректно читаются и записываются. Для отладки динамических форм удобно временно выводить список созданных элементов через Сообщить() в конце процедуры построения.

Если требуется не добавить новое событие, а изменить поведение существующего элемента типовой формы, альтернативой служит механизм расширений с аннотациями &После, &Вместо, &Перед для обработчиков. Это безопаснее для обновлений, чем прямое изменение типового модуля. Для простых сценариев, где нужна лишь реакция на изменение реквизита, иногда достаточно переопределить типовой обработчик в расширении, не создавая элементы программно вовсе.

Контрольные точки

Как проверить результат

Отображение элемента
Норма

Элемент виден в нужной группе формы с заданным заголовком

Тревожный признак

Элемент отсутствует — проверьте родителя и порядок вызова Элементы.Добавить

Срабатывание события
Норма

Точка останова в обработчике срабатывает при действии пользователя

Тревожный признак

Обработчик не вызывается — проверьте директиву компиляции и имя процедуры

Работа с данными
Норма

Значение поля сохраняется в реквизит формы и читается обратно

Тревожный признак

Поле пустое после ввода — не задано свойство ПутьКДанным

Итог

Что важно запомнить

Событие назначается методом УстановитьДействие с указанием имени события и имени процедуры модуля формы. Обработчик объявляется заранее с правильной сигнатурой, код создания элементов выполняется на сервере, для кнопок используется механизм команд, а доработку типовых форм безопаснее делать через расширения.

Частые вопросы

Можно ли назначить событию процедуру из общего модуля?

Нет, напрямую нельзя: УстановитьДействие принимает имя процедуры только из модуля текущей формы. Обходной путь — создать в форме процедуру-прокладку, которая вызывает нужный метод общего модуля и передаёт ему параметры.

Можно ли удалить или заменить ранее назначенное событие?

Да, повторный вызов УстановитьДействие для того же события заменяет обработчик на новый. Передать пустую строку вместо имени процедуры нельзя — для «отключения» события назначьте процедуру-заглушку без действий.

Почему обработчик с директивой &НаСервере не вызывается?

Интерактивные события элементов формы (Нажатие, ПриИзменении и подобные) формируются на клиенте, поэтому обработчик должен быть клиентским или клиент-серверным. Серверную логику вызывайте из клиентского обработчика отдельным серверным методом.

Как передать в обработчик дополнительный параметр?

Сигнатуру обработчика менять нельзя, поэтому дополнительные данные хранят в реквизитах формы или кодируют в имени элемента (например, Кнопка_Печать_СчетНаОплату) и извлекают внутри обработчика через Элемент.Имя.

Работает ли УстановитьДействие в обычных формах?

Нет, метод относится к управляемым формам. В обычных формах обработчики динамическим элементам назначаются иначе — через конструкцию с назначением действий при создании элемента, и сам набор возможностей там отличается.

Почему динамические элементы пропадают после серверного вызова?

При обращении к серверу форма пересоздаётся, и элементы, добавленные кодом, теряются, если процедура их построения не вызывается повторно. Вынесите создание элементов в отдельную процедуру и вызывайте её при каждом событии, требующем актуального состава формы.