При разработке сложных форм в 1С:Документооборот часто возникает задача динамического управления интерфейсом: скрытия, отображения или установки обязательности для огромного количества дополнительных реквизитов. Стандартные механизмы БСП хороши, но иногда их функционала недостаточно, и возникает потребность в собственном обработчике, который бы срабатывал при любом изменении элементов формы.
Рассмотрим, как реализовать подобный функционал, не нарушая работу уже существующих процедур и не конфликтуя с типовым кодом.
Одной из главных проблем при попытке программно присвоить общий обработчик всем элементам формы является то, что при использовании метода УстановитьДействие() вы «затираете» уже назначенные ранее процедуры. Чтобы избежать этого, мы должны сохранить старый обработчик перед установкой нового. Разберем этот процесс по шагам.
ПриИзменении.Подсказку, хотя более архитектурно правильно использовать массив или структуру в реквизитах формы).Посмотрим на пример реализации такой логики:
Процедура ИнициализироватьОбработчики()
Для Каждого Элемент Из Элементы Цикл
Если ТипЗнч(Элемент) = Тип("ПолеФормы") Тогда
// Сохраняем имя старого обработчика в подсказку
СтароеДействие = Элемент.ПолучитьДействие("ПриИзменении");
Если СтароеДействие <> Неопределено Тогда
Элемент.Подсказка = Формат(СтароеДействие, "С");
КонецЕсли;
// Устанавливаем новый общий обработчик
Элемент.УстановитьДействие("ПриИзменении", "ОбщийОбработчикПриИзменении");
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Теперь в процедуре ОбщийОбработчикПриИзменении нам нужно проверить, было ли у элемента старое действие, и если было — выполнить его. Это обеспечит корректную работу типового функционала БСП или других модулей.
&НаКлиенте
Процедура ОбщийОбработчикПриИзменении(Элемент)
// 1. Выполняем нашу логику проверки условий и изменения видимости
ВыполнитьЛогикуПересчета(Элемент);
// 2. Выполняем старый обработчик, если он был сохранен
ИмяСтарогоОбработчика = Элемент.Подсказка;
Если ЗначениеЗаполнено(ИмяСтарогоОбработчика) Тогда
Выполнить(ИмяСтарогоОбработчика + "(Элемент)");
КонецЕсли;
КонецПроцедуры
Важно понимать, что использование Выполнить() и хранение имен процедур в Подсказке — это вынужденная мера. В современных версиях платформы 1С:Предприятие 8.3 существует более правильный механизм — Расширения конфигурации.
Вместо перехвата событий в коде формы, мы можем использовать аннотации &После. Это позволяет:
Выполнить() может быть ограничено в облачных средах.Для этого в расширении необходимо подключить нужную форму и в модуле формы создать обработчик:
&После("ПриИзмененииПоляВвода")
Процедура МойОбработчик_После(Элемент)
// Здесь мы выполняем дополнительную логику,
// типовой код уже отработал до этого момента
ОбновитьВидимостьДопРеквизитов(ЭтаФорма);
КонецПроцедуры
Авторы темы справедливо опасались частых «прыжков» на сервер при каждом изменении поля. Чтобы избежать лагов интерфейса, рекомендуем использовать механизм отложенного выполнения:
Вместо немедленного вызова сервера в ПриИзменении, подключайте ОбработчикОжидания с задержкой, например, 0.5 секунды. Если за это время пользователь изменит еще одно поле, сбрасывайте таймер и запускайте отсчет заново. Это называется паттерн Debounce. Таким образом, серверный запрос уйдет только тогда, когда пользователь закончил ввод данных, что значительно повысит производительность 1С:Документооборот.
Подводя итог: если вам требуется быстрое решение «здесь и сейчас», метод сохранения имени обработчика в свойства элемента поможет. Но для долгосрочной разработки и поддержки конфигурации мы настоятельно рекомендуем переходить на использование Расширений и Обработчиков ожидания для оптимизации серверной нагрузки.