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