Почему сбрасывается текст при автоподборе в управляемой форме 1С и как это исправить?

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

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

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

Анализ проблемы: как проявляется ошибка

Проанализируем типичный сценарий, описанный разработчиком. На управляемой форме есть реквизит, в котором переопределено событие автоподбора. Задача — выполнить запрос к базе данных с учетом доступных пользователю ограничений (RLS) или других специфичных отборов и вернуть готовый список значений.

Код обработчика события на клиенте выглядит примерно так:


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

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

Внутри процедуры ПолучитьДанныеВыбораСУчетомОтборов происходит вызов сервера для выполнения запроса к базе данных. И именно здесь кроется главная ошибка.

Симптомы ошибки на стороне пользователя:

  1. Пользователь начинает вводить слово, например, «работа».
  2. Он нажимает клавишу «р».
  3. Срабатывает событие АвтоПодбор, платформа делает паузу, показывает выпадающий список со значениями, начинающимися на «р».
  4. В этот же момент буква «р» исчезает из поля ввода. Реквизит визуально становится пустым.
  5. Пользователь продолжает печатать и нажимает «а».
  6. В пустом поле появляется «а», снова срабатывает автоподбор, и список обновляется уже для буквы «а», стирая предыдущий результат поиска.

Почему очищается поле ввода? Выясним причину

Главная причина кроется в архитектуре клиент-серверного взаимодействия управляемых форм 1С. Когда вы печатаете текст в поле ввода, это значение существует только на клиенте (в браузере или тонком клиенте). Оно еще не связано с основным реквизитом формы, так как ввод не завершен.

Если в момент набора текста происходит контекстный серверный вызов (процедура с директивой &НаСервере), платформа выполняет полную сериализацию данных формы. Она отправляет текущее состояние формы на сервер, выполняет там код, а затем возвращает измененное состояние формы обратно на клиент. При этом процессе платформа обновляет отображение всех элементов управления в соответствии с данными, пришедшими с сервера.

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

Решение проблемы: используем вызов без контекста

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

Рассмотрим по шагам, как исправить код.

Шаг 1. Перенесите логику получения данных выбора в отдельную функцию и назначьте ей директиву компиляции &НаСервереБезКонтекста. Это укажет платформе, что на сервер нужно передать только явно указанные параметры (в нашем случае — текст для поиска), без отправки всех реквизитов формы.


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

КонецФункции

Шаг 2. Настройте вызов этой функции в клиентском обработчике события АвтоПодбор. Обратите внимание, что мы заполняем параметр ДанныеВыбора результатом выполнения нашей бесконтекстной функции.


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

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

Резюме и дополнительные рекомендации

При использовании директивы &НаСервереБезКонтекста клиент-серверное взаимодействие происходит максимально быстро. Форма не тратит ресурсы и время на сериализацию данных, и, самое главное, при возврате на клиент интерфейс не перерисовывается принудительно. Текст, который вводит пользователь, остается в поле, и ввод следующих символов происходит плавно и предсказуемо.

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

← На главную