Как назначить обработчик события в форме и модуле 1С
Содержание
Обработчик назначают в трёх местах: для события элемента или формы — через палитру свойств в редакторе форм (кнопка с лупой рядом с событием создаёт процедуру в модуле формы); для события объекта (ПередЗаписью, ПриЗаписи) — в модуле объекта; для чужого объекта без правки его модуля — через подписку на события в дереве конфигурации.
Событие — это момент, когда платформа передаёт управление вашему коду: пользователь открыл форму, изменил поле, система собирается записать документ. Обработчик — процедура, которую платформа вызовет в этот момент. Разберём каждый способ назначения с точными путями, директивами компиляции и примерами кода для 1С 8.3 (интерфейс «Такси»).
Где возникают события и какие бывают обработчики
События в платформе делятся по тому, кто их порождает:
- 🖱️ События элементов формы — реакция на действия пользователя:
ПриИзмененииполя,Нажатиекнопки,Выборв списке,АвтоПодборв строке ввода. Выполняются на клиенте. - 🪟 События формы — жизненный цикл формы:
ПриСозданииНаСервере,ПриОткрытии,ПередЗакрытием,ПриПовторномОткрытии. Часть выполняется на сервере, часть на клиенте. - 💾 События объекта — запись и проверка данных:
ПередЗаписью,ПриЗаписи,ПередУдалением,ОбработкаПроверкиЗаполнения,ОбработкаЗаполнения. Выполняются на сервере, в модуле объекта.
Одно и то же действие может поднять цепочку событий. Нажали «Провести и закрыть» — сработают клиентское ПередЗаписью формы, затем серверные ПередЗаписью и ПриЗаписи объекта, потом ОбработкаПроведения. Понимание порядка важно: если проверку поставить не в то событие, она либо не остановит запись, либо сработает слишком поздно.
Отдельно стоит развести два события, которые часто путают при открытии формы. ПриСозданииНаСервере выполняется на сервере один раз при создании формы — сюда ставят заполнение реквизитов значениями по умолчанию, настройку видимости и доступности элементов, установку условного оформления. ПриОткрытии выполняется позже и уже на клиенте — здесь уместны действия, которым нужен клиент: открытие вспомогательной формы, вопрос пользователю, запуск оповещения. Если заполнение данных
поставить в ПриОткрытии, оно будет происходить после того, как форма уже показана, и пользователь успеет увидеть пустые поля.
Полный список событий конкретного объекта или элемента всегда виден в палитре свойств в разделе «События» — платформа показывает только те, что применимы к выделенному объекту.
Назначение обработчика в редакторе форм
Самый частый способ. Открываете форму в конфигураторе (ветка Формы объекта → двойной клик по форме), выделяете элемент или корень формы.
- Откройте палитру свойств: правый клик по элементу →
Свойства, либоAlt+Enter. - Прокрутите до раздела События.
- Найдите нужное событие (например,
ПриИзмененииу поля ввода). - Нажмите кнопку с лупой справа от строки события.
Платформа создаст в модуле формы процедуру с правильным именем и директивой компиляции и свяжет её со свойством события. Имя по умолчанию складывается из имени элемента и события: у поля Цена обработчик ПриИзменении получит имя ЦенаПриИзменении.
&НаКлиенте
Процедура ЦенаПриИзменении(Элемент)
Сумма = Количество * Цена;
КонецПроцедуры
Если процедура уже есть и вы хотите привязать её вручную, впишите имя в строку события без скобок и параметров — просто ЦенаПриИзменении. Привязка идёт по имени: переименуете процедуру в модуле — обязательно поправьте имя в свойстве события, иначе обработчик перестанет вызываться.
Для кнопки принцип тот же. Выделите кнопку, в разделе «События» найдите Нажатие, нажмите лупу. Внутри обработчика размещаете то, что должно происходить по нажатию:
&НаКлиенте
Процедура РассчитатьНажатие(Кнопка)
Если НЕ ЗначениеЗаполнено(Контрагент) Тогда
Сообщить("Сначала выберите контрагента");
Возврат;
КонецЕсли;
ВыполнитьРасчётНаСервере();
КонецПроцедуры
Обратите внимание на параметр процедуры: у события ПриИзменении платформа передаёт Элемент, у Нажатие — Кнопка. Набор параметров у каждого события свой и менять его нельзя — удалите лишний параметр, и код не скомпилируется. Поэтому заготовку надёжнее получать лупой: она подставит правильную сигнатуру.
Для работы с выбором значений пригодятся два связанных события. Выбор у поля ввода срабатывает, когда пользователь жмёт кнопку выбора и открывает форму подбора. ОбработкаВыбора — событие уже самой формы: оно отрабатывает, когда из открытой формы подбора вернулось значение (форма подбора отдаёт его методом ОповеститьОВыборе). Эту пару назначают, когда нужен нестандартный подбор — например, открыть свою форму списка с предварительным отбором вместо стандартного выбора из справочника.
Обработчики в модуле объекта
События записи, удаления и проверки живут не в форме, а в модуле объекта. Форм у справочника или документа может быть несколько, а модуль объекта один — поэтому логику записи размещают именно там.
Открыть модуль
: в дереве конфигурации правый клик по объекту → Открыть модуль объекта. В верхней части редактора модуля есть выпадающий список процедур-обработчиков — выберите нужное событие, и платформа вставит заготовку.
Типичный обработчик проверки перед записью:
Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
Если ЗначениеЗаполнено(Контрагент) И НЕ ЗначениеЗаполнено(ДоговорКонтрагента) Тогда
Сообщить("Не выбран договор");
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
Процедуры модуля объекта выполняются на сервере — директива компиляции здесь не ставится. Через параметр Отказ = Истина вы отменяете запись: платформа прервёт операцию и вернёт пользователю сообщение.
| Событие | Когда срабатывает | Для чего использовать |
|---|---|---|
ОбработкаПроверкиЗаполнения | по команде проверки и перед записью | контроль обязательных полей |
ПередЗаписью | до начала записи в транзакции | подготовка данных, отказ от записи |
ПриЗаписи | внутри транзакции записи | запись связанных данных |
ПередУдалением | до удаления объекта | проверка ссылок, запрет удаления |
Код в ПриЗаписи выполняется внутри транзакции. Долгие операции и обращения к внешним системам сюда не ставьте — транзакция будет держать блокировки, пока код не отработает.
Подписки на события: обработка без правки модуля
Отдельный механизм, который экономит время практику. Подписка позволяет назначить обработчик события сразу для нескольких объектов и не трогать их модули — удобно, когда правите типовую конфигурацию и хотите обойтись расширением.
Создаётся в дереве: ветка Общие → Подписки на события → добавить. У подписки три главных свойства:
- Источник — составной тип: отметьте объекты, чьё событие перехватываете (например, несколько документов сразу).
- Событие — выбирается из списка доступных для выбранных источников (
ПередЗаписью,ПриЗаписии т. д.). - Обработчик — экспортная процедура в общем модуле.
Общий модуль, где лежит обработчик, должен компилироваться на сервере (флаг Сервер в свойствах модуля). Сигнатура процедуры повторяет параметры события плюс первым идёт источник:
// Общий модуль с флагом «Сервер»
Процедура ПроверитьДатуДокумента(Источник, Отказ) Экспорт
Если Источник.Дата < НачалоГода(ТекущаяДата()) Тогда
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
Подписки на события и обработчики в самих модулях объектов выполняются независимо — для одного события отработают оба. Если их несколько, порядок вызова подписок платформой не гарантируется, поэтому не стройте логику на том, что одна подписка выполнится раньше другой.
Директивы компиляции: клиент, сервер и контекст
В модуле управляемой формы каждая процедура помечается директивой — она определяет, где код выполняется и имеет ли доступ к данным формы.
&НаКлиенте— на клиенте, есть контекст формы. Сюда идут обработчики событий элементов, потому что действия пользователя происходят на клиенте.&НаСервере— на сервере, с контекстом формы: можно читать и менять реквизиты формы, обращаться к базе.&НаСервереБезКонтекста— на сервере, без контекста формы. Работает быстрее, годится для вспомогательных расчётов, которым форма не нужна.&НаКлиентеНаСервереБезКонтекста— компилируется и там, и там.
Ключевое правило: обработчик события элемента формы вызывается на клиенте, поэтому он всегда &НаКлиенте. Если внутри нужно обратиться к базе, вынесите эту часть в серверную процедуру и вызовите её:
&НаКлиенте
Процедура КонтрагентПриИзменении(Элемент)
ЗаполнитьДоговорПоУмолчанию();
КонецПроцедуры
&НаСервере
Процедура ЗаполнитьДоговорПоУмолчанию()
Договор = Справочники.ДоговорыКонтрагентов.ОсновнойДоговор(Контрагент);
КонецПроцедуры
Событие ПриСозданииНаСервере само по себе серверное (&НаСервере), а ПриОткрытии и ПередЗакрытием — клиентские (&НаКлиенте). Лупа в палитре свойств подставляет правильную директиву автоматически — это ещё один повод создавать обработчики через неё, а не вписывать вручную.
Динамическое назначение обработчика в коде
Иногда обработчик нужно привязать не в конструкторе, а программно — например, в зависимости от настроек. Для элементов формы есть метод УстановитьДействие:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Элементы.Цена.УстановитьДействие("ПриИзменении", "ЦенаПриИзменении");
КонецПроцедуры
Первый параметр — имя события строкой, второй — имя клиентской процедуры модуля формы (тоже строкой). Процедура ЦенаПриИзменении должна существовать в модуле с директивой &НаКлиенте. Пустая строка во втором параметре снимает обработчик.
Для событий прикладных объектов в коде есть пара операторов ДобавитьОбработчик и УдалитьОбработчик:
ДобавитьОбработчик Источник.ПередЗаписью, ЭтотОбъект.ПроверкаПередЗаписью;
Применяют их реже — в основном при работе с объектами, события которых нужно обрабатывать по ходу выполнения. Подписку на события такой код не заменяет: подписка настраивается в конфигурации и работает всегда, а оператор действует только в пределах текущего сеанса, пока объект существует в памяти.
Важная тонкость: программная установка значения реквизита не вызывает событие ПриИзменении. Платформа поднимает его только на действие пользователя. Если присвоили значение в коде и нужна та же логика — вызовите процедуру пересчёта напрямую.
Отладка обработчиков и типичные ошибки
Проверить, что обработчик назначен и вызывается, проще всего отладчиком. Поставьте точку останова (F9) на первой строке процедуры, запустите приложение в режиме отладки и выполните действие. Если управление в процедуру не зашло — обработчик не привязан или вы ждёте событие, которое при этом действии не поднимается.
Инструменты отладки:
- Точка останова (
F9) — остановка на строке. - Шаг с заходом / с обходом (
F11/F10) — построчное выполнение. - Табло — просмотр значений переменных в момент останова.
- Остановка по ошибке — настраивается в меню отладки, ловит исключение в момент возникновения.
&НаКлиенте, но обращается к базе. Вынесите серверную часть в отдельную &НаСервере процедуру и вызовите её.Ещё одна частая путаница — клиент и сервер. Внутри клиентского обработчика нельзя напрямую читать базу и вызывать серверные методы объектов; нужно уйти на сервер отдельной процедурой. И наоборот: из серверной процедуры без контекста (&НаСервереБезКонтекста) не видны реквизиты формы — обращение к ним даст ошибку компиляции.
Частые вопросы
Чем модуль формы отличается от модуля объекта?
Можно ли назначить один обработчик на несколько элементов?
Элемент, который платформа передаёт в процедуру.Как снять ранее назначенный обработчик?
УстановитьДействие с пустой строкой во втором параметре для элемента формы или оператор УдалитьОбработчик для события объекта.Почему обработчик `ПередЗаписью` не останавливает запись?
Отказ = Истина внутри процедуры. Если просто вывели сообщение без установки Отказ, платформа продолжит запись. Проверьте, что присваиваете параметру Отказ значение Истина.