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

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

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

Разберем детально механизм возникновения этой проблемы и рассмотрим надежные способы реализации поиска без потери вводимых данных.

Причины сброса текста при вводе

Выясним причину, почему платформа 1С очищает поле ввода при попытке выполнить серверные действия в обработчике изменения текста:

  1. Несинхронизированность буфера ввода и реквизита формы. В момент возникновения события ИзменениеТекстаРедактирования введенный пользователем текст существует только в локальном экранном буфере элемента управления на клиенте. Связанный с этим полем реквизит формы еще не обновлен — он содержит старое (или пустое) значение. При выполнении контекстного серверного вызова (например, для установки отбора в динамическом списке) платформа передает состояние формы на сервер и возвращает его обратно. В процессе обратной синхронизации данные реквизита перезаписывают содержимое элемента на клиенте, и набранный текст исчезает.
  2. Автоматическое выделение текста и автоподбор. Событие ИзменениеТекстаРедактирования предшествует системному событию АвтоПодбор. Если не отключить стандартную обработку, платформа может выделить весь набранный текст. В результате при вводе следующей буквы выделенный фрагмент стирается.
  3. Обновление текста редактирования. Свойство элемента формы ОбновлениеТекстаРедактирования по умолчанию настроено таким образом, что при изменении данных формы фокус или позиция курсора сбрасываются.

Способ 1. Использование события ПриИзменении вместо ИзменениеТекстаРедактирования

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

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


&НаКлиенте
Процедура ПолеПоискаПриИзменении(Элемент)
    УстановитьОтборСпискаНаСервере();
КонецПроцедуры

&НаСервере
Процедура УстановитьОтборСпискаНаСервере()
    // Установка отбора в динамическом списке Список
    ЭлементОтбора = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Наименование");
    ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Содержит;
    ЭлементОтбора.ПравоеЗначение = ПолеПоиска;
    ЭлементОтбора.Использование = ЗначениеЗаполнено(ПолеПоиска);
КонецПроцедуры

Способ 2. Реализация живого поиска через обработчик ожидания (Debounce)

Если требуется именно динамическая фильтрация «на лету», правильным подходом является использование обработчика ожидания. Это позволяет дождаться, пока пользователь сделает паузу в наборе текста, избежать множества лишних серверных вызовов и предотвратить сброс фокуса.

Разберем по шагам реализацию данного паттерна:

  1. В процедуре ИзменениеТекстаРедактирования отключаем стандартную обработку, сохраняем текущий текст в реквизит формы на клиенте и перезапускаем однократный обработчик ожидания.
  2. В свойствах элемента управления устанавливаем свойство ОбновлениеТекстаРедактирования в значение НеИспользовать.
  3. В процедуре ожидания выполняем серверный вызов для применения отбора.

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


&НаКлиенте
Процедура ПолеПоискаИзменениеТекстаРедактирования(Элемент, Текст, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;
    
    // Синхронизируем значение реквизита с введенным текстом на клиенте
    ПолеПоиска = Текст;
    
    // Перезапускаем обработчик ожидания с задержкой 0.4 секунды
    ОтключитьОбработчикОжидания("ПрименитьОтборПоиска");
    ПодключитьОбработчикОжидания("ПрименитьОтборПоиска", 0.4, Истина);
КонецПроцедуры

&НаКлиенте
Процедура ПрименитьОтборПоиска()
    УстановитьОтборСпискаНаСервере();
КонецПроцедуры

Способ 3. Использование стандартной строки поиска динамического списка

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

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

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

← На главную