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