Почему при событии АвтоПодбор в поле ввода стирается текст и как это исправить

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

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

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

Причина первая: неверный тип в параметре ДанныеВыбора

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

Параметр ДанныеВыбора платформы 1С строго ожидает объект типа СписокЗначений. Если передать туда неподдерживаемый тип данных, в контекстном окне интерфейса появится сообщение о том, что ничего не найдено, даже если запрос на сервере успешно вернул строки.

Причина вторая: контекстный вызов сервера (&НаСервере)

Стирание только что набранных символов в поле ввода — наиболее частая и неочевидная ошибка при работе с интерактивными событиями ввода. Выясним причину этой проблемы.

Когда мы вызываем серверную процедуру или функцию с директивой &НаСервере, платформа выполняет полный контекстный вызов. В этот момент на сервер передается все состояние управляемой формы, а при возврате результата на клиент происходит обратная синхронизация реквизитов формы. Текст, который пользователь только что начал вводить в поле ввода и еще не зафиксировал (не нажал клавишу Enter и не сместил фокус), заменяется сохраненным в реквизите значением. В итоге набранный символ сбрасывается или выделяется полностью, а последующее нажатие клавиши затирает его заново.

Главное правило: любые функции получения данных, вызываемые из обработчиков набора текста и автоподбора, должны иметь директиву &НаСервереБезКонтекста. При безконтекстном вызове состояние формы не гоняется между клиентом и сервером, благодаря чему введенные пользователем символы и позиция курсора остаются на месте.

Правильная реализация события АвтоПодбор

Соберем корректный рабочий пример. Нам необходимо реализовать клиентский обработчик и серверную функцию без контекста, возвращающую СписокЗначений. Также важно оптимизировать запрос: добавить ограничение количества строк и исключить лишние запросы на пустой ввод.

Разберем по шагам правильный программный код:


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

&НаКлиенте
Процедура НаименованиеАвтоПодбор(Элемент, Текст, ДанныеВыбора, ПараметрыПолученияДанных, Ожидание, СтандартнаяОбработка)
    
    // Проверяем минимальную длину строки для снижения нагрузки на СУБД
    Если СтрДлина(СокрЛП(Текст)) < 2 Тогда
        Возврат;
    КонецЕсли;
    
    // Отключаем стандартный поиск платформы
    СтандартнаяОбработка = Ложь;
    
    // Передаем сформированный список значений в ДанныеВыбора
    ДанныеВыбора = ПолучитьСписокНаименований(Текст);
    
КонецПроцедуры

Тонкости оптимизации и подводные камни

При использовании автоподбора важно учитывать следующие технические нюансы:

  1. Ограничение выборки через ПЕРВЫЕ N. При наборе одной распространенной буквы (например, «А» или «О») запрос без ограничения может вернуть тысячи записей. Это вызовет серьезное замедление работы интерфейса. Обязательно ограничивайте результат 15–20 первыми строками.
  2. Анализ параметра Ожидание. Параметр Ожидание содержит время в секундах, прошедшее с момента ввода. Если значение равно нулю, событие может вызываться служебными механизмами платформы, а не прямым набором текста.
  3. Тип элементов списка значений. Если поле ввода связано со строковым реквизитом, элементы списка должны содержать строки, а не ссылки справочника (СправочникСсылка). Иначе при выборе подсказки произойдет попытка преобразования типов или в поле запишется строковое представление ссылки.

Альтернативные способы контроля дублей

Событие АвтоПодбор предназначено преимущественно для быстрого выбора уже существующего элемента. Если задача состоит лишь в том, чтобы предупредить пользователя о наличии похожих наименований при создании нового объекта, этот механизм может быть неудобен: случайное нажатие клавиши выбора сотрет введенный пользователем уникальный текст существующим значением.

В таких случаях эффективнее использовать следующие подходы:

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