Как программно назначить обработчик события ПриИзменении в расширении формы 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Анализ исходной ситуации

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

Посмотрим на пример кода, который изначально не работал у автора темы:


// В процедуре ПриСозданииНаСервереПосле модуля формы расширения
ДополнительныйРеквизит = Элементы.Вставить("ПРФ_НаименованиеПолное", Тип("ПолеФормы"), Элементы.ГруппаНаименованиеКод);
ДополнительныйРеквизит.ПутьКДанным = "Объект.ПРФ_НаименованиеПолное";
ДополнительныйРеквизит.УстановитьДействие("ПриИзменении", "ПРФ_НаименованиеПолноеПриИзменении");

На первый взгляд все верно. Однако при изменении данных в поле ПРФ_НаименованиеПолное процедура-обработчик не вызывалась. Проанализируем, почему это происходит и как это исправить.

Причина 1: Директивы компиляции

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

Если вы объявите процедуру без директивы или с директивой &НаСервере, платформа не сможет связать клиентское событие элемента управления с серверным кодом напрямую, и обработчик попросту проигнорируется (или вызовет ошибку, если платформа не сможет найти процедуру в соответствующем контексте).

Правильное объявление процедуры:


&НаКлиенте
Процедура ПРФ_НаименованиеПолноеПриИзменении(Элемент)
    // Логика обработки изменения
    Наименование = ПолучитьПоследнююЧастьНаименования(Объект.ПРФ_НаименованиеПолное);
КонецПроцедуры

Причина 2: Сигнатура процедуры (параметры)

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

Проанализируем требования к параметрам:

  1. Процедура должна принимать ровно столько параметров, сколько предусмотрено для данного типа события в документации 1С.
  2. Для ПриИзменении сигнатура выглядит как ИмяПроцедуры(Элемент).
  3. Даже если вы не планируете использовать переменную Элемент внутри кода, ее наличие в заголовке процедуры гарантирует корректный вызов платформой.

Разберем по шагам правильный алгоритм реализации

Чтобы программное добавление обработчика через расширение работало стабильно, рекомендуем придерживаться следующей последовательности действий:

Шаг 1. Подготовка реквизитов. Убедитесь, что реквизиты добавлены в расширение и привязаны к объекту (например, к справочнику). Если реквизиты формы добавляются программно, используйте метод ИзменитьРеквизиты() перед созданием элементов.

Шаг 2. Создание элемента формы. В процедуре ПриСозданииНаСервере (с аннотацией &После) создаем элемент:


&НаСервере
Процедура ПРФ_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
    
    // Проверяем, не создан ли элемент ранее
    Если Элементы.Найти("ПРФ_НаименованиеПолное") = Неопределено Тогда
        
        Группа = Элементы.ГруппаНаименованиеКод;
        НовыйЭлемент = Элементы.Вставить("ПРФ_НаименованиеПолное", Тип("ПолеФормы"), Группа);
        НовыйЭлемент.Вид = ВидПоляФормы.ПолеВвода;
        НовыйЭлемент.ПутьКДанным = "Объект.ПРФ_НаименованиеПолное";
        
        // Устанавливаем действие. 
        // ВАЖНО: Имя процедуры указывается как строка, сама процедура должна быть в этом же модуле.
        НовыйЭлемент.УстановитьДействие("ПриИзменении", "ПРФ_НаименованиеПолноеПриИзменении");
        
    КонецЕсли;
    
КонецПроцедуры

Шаг 3. Создание обработчика в модуле формы. Спускаемся в конец модуля формы расширения и добавляем процедуру с правильной директивой:


&НаКлиенте
Процедура ПРФ_НаименованиеПолноеПриИзменении(Элемент)
    
    // Пример логики: обработка данных
    Сообщить("Значение реквизита изменено!");
    // Здесь ваш код работы с данными объекта
    
КонецПроцедуры

Важные нюансы работы с методом УстановитьДействие()

Проанализируем дополнительные технические моменты, которые могут повлиять на работу вашего кода:

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

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

3. Использование в расширениях. В расширениях крайне важно, чтобы форма была заимствована корректно. Если вы добавляете программный код в модуль формы, убедитесь, что сама форма включена в расширение, иначе изменения в ее модуле не будут применены.

4. Контроль параметров. Платформа 1С версии 8.3 в некоторых режимах совместимости может не выдавать ошибку при несоответствии количества параметров, но в новых версиях и при строгом контроле это приведет к аварийному завершению работы расширения. Всегда добавляйте (Элемент) для событий элементов управления.

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

← На главную