Почему не срабатывает событие ПриИзменении у поля на форме в 1С?

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

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

Проанализируем типичный случай: на форме документа есть поле "Клиент". Мы хотим, чтобы при выборе клиента выполнялся какой-то код. Мы создаем обработчик события ПриИзменении, но он не вызывается. При этом, если привязать этот же обработчик к полю "Комментарий", все работает. Это верный знак, что проблема не в коде обработчика и не в механизме событий в целом, а в чем-то, связанном именно с полем "Клиент".

Основная причина: обработчик назначен не тому элементу формы

Самая распространенная причина такого поведения на сложных управляемых формах — обработчик события привязан не к тому элементу, с которым вы на самом деле взаимодействуете в пользовательском режиме.

Современные формы в 1С могут быть устроены очень хитро. Визуально вы можете видеть одно поле для ввода, но в дереве элементов формы их может быть несколько, и они могут отвечать за разные состояния или представления одних и тех же данных. Например:

В разобранной на форуме ситуации пользователь пытался назначить событие на элемент с именем "Клиент" или "Партнер", в то время как реальный, активный для ввода элемент, с которым он работал, назывался ПартнерБезКЛ. Система, естественно, не вызывала событие, так как изменялся совсем другой элемент.

Как найти правильный элемент и настроить событие

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

  1. Откройте нужную форму в конфигураторе.
  2. В редакторе формы найдите визуально то самое поле, которое вы изменяете в режиме "Предприятие". Кликните на него мышкой.
  3. После клика в палитре "Свойства" (обычно справа внизу) отобразятся свойства именно этого, выделенного элемента. Посмотрите на свойство "Имя". Это и есть то уникальное имя, которое нам нужно.
  4. Не снимая выделения с элемента, перейдите в его свойствах на вкладку "События".
  5. Найдите событие ПриИзменении и нажмите на значок лупы (🔍) справа от поля ввода. Конфигуратор автоматически создаст в модуле формы процедуру-обработчик с правильным именем (например, ИмяЭлементаПриИзменении) и свяжет ее с элементом.

Важно: Использование "лупы" — самый надежный способ создания обработчика. Это исключает опечатки в имени процедуры и гарантирует правильную привязку к элементу и событию.

Порядок действий для правильной обработки изменения

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

Правильная структура кода выглядит так:


&НаКлиенте
Процедура МоеПолеКлиентПриИзменении(Элемент)
    
    // Сначала можно выполнить быстрые проверки на клиенте
    Если Объект.Клиент.Пустая() Тогда
        Возврат; // Если поле очистили, выходим
    КонецЕсли;

    // Вызываем серверную процедуру для выполнения основной логики
    ЗаполнитьДанныеПоКлиентуНаСервере();
    
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьДанныеПоКлиентуНаСервере()
    
    // Здесь выполняется код, требующий доступа к базе данных
    // Например, находим договор по умолчанию для выбранного клиента
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ ПЕРВЫЕ 1
        |    ДоговорыКонтрагентов.Ссылка
        |ИЗ
        |    Справочник.ДоговорыКонтрагентов КАК ДоговорыКонтрагентов
        |ГДЕ
        |    ДоговорыКонтрагентов.Владелец = &Владелец
        |    И ДоговорыКонтрагентов.Основной";

    Запрос.УстановитьПараметр("Владелец", Объект.Клиент);
    
    РезультатЗапроса = Запрос.Выполнить();
    Если Не РезультатЗапроса.Пустой() Тогда
        Выборка = РезультатЗапроса.Выбрать();
        Выборка.Следующий();
        Объект.Договор = Выборка.Ссылка;
    КонецЕсли;
    
КонецПроцедуры

Такая схема является стандартной и наиболее правильной при работе с управляемыми формами: клиентская часть реагирует на действие пользователя, а серверная — выполняет ресурсоемкие операции с данными.

Когда еще может не срабатывать `ПриИзменении`

Рассмотрим еще одну частую причину — программное изменение значения поля.

Событие ПриИзменении срабатывает только при интерактивном изменении, то есть когда пользователь сам меняет значение в поле. Если значение реквизита меняется программно из другого участка кода, событие автоматически не вызывается. Это сделано для предотвращения зацикливания.

Если вам необходимо, чтобы после программного изменения все-таки выполнилась логика из обработчика ПриИзменении, используйте специальный метод ОповеститьОбИзменении().

Посмотрим на пример:


&НаКлиенте
Процедура ЗаполнитьКлиентаПоУмолчанию()

    // Находим нужного клиента и присваиваем его реквизиту объекта
    // Предположим, что функция НайтиКлиентаПоУмолчанию() возвращает ссылку на клиента
    НайденныйКлиент = НайтиКлиентаПоУмолчанию(); 
    Объект.Клиент = НайденныйКлиент;
    
    // В этот момент событие "КлиентПриИзменении" НЕ сработает автоматически.
    // Чтобы его запустить, нужно вызвать оповещение.
    // В качестве параметра передается измененное значение.
    ОповеститьОбИзменении(НайденныйКлиент);

КонецПроцедуры

Вызов ОповеститьОбИзменении() имитирует интерактивное изменение данных, к которым привязано поле, и запускает все связанные с ним обработчики событий.

Таким образом, если у вас не работает событие ПриИзменении, в первую очередь убедитесь, что вы привязали обработчик к правильному элементу формы, и проверьте, не изменяется ли значение поля программно без последующего оповещения.

← На главную