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

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

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

Причины сброса текста и основные ошибки реализации

Рассмотрим ключевые факторы, которые приводят к очистке поля ввода или потере введенных символов:

  1. Использование контекстных вызовов формы (&НаСервере). В обработчике события АвтоПодбор категорически запрещено использовать контекстные серверные процедуры и функции. При контекстном вызове состояние всей формы передается на сервер и возвращается обратно на клиент. Это инициирует обновление элементов интерфейса, что сбрасывает текущий буфер редактирования поля ввода. Согласно синтакс-помощнику, вызовы должны быть строго &НаСервереБезКонтекста.
  2. Прямая модификация свойства Элемент.СписокВыбора на лету. Попытка очистить и заново наполнить коллекцию СписокВыбора непосредственно в момент набора текста переинициализирует внутренний контекст элемента управления. В результате фокус и введенный текст могут быть сброшены.
  3. Настройка свойства «Обновление текста редактирования». Если у поля ввода включен неподходящий режим обновления или включен строгий РежимВыбораИзСписка, платформа пытается немедленно сопоставить введенный текст со значениями списка. Не найдя соответствия при вводе пробела, платформа очищает значение.
  4. Ошибки в цикле заполнения массива. Нередко встречается ошибка алгоритма, когда внутри цикла Для Сч = 0 По ... разработчик вручную выполняет Сч = Сч + 1;. Поскольку управляющая конструкция сама инкрементирует переменную на каждом шаге, шаг цикла удваивается, и ровно половина найденных значений теряется.

Шаг 1. Перевод серверного вызова в неконтекстный вид

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

Посмотрим на пример правильного оформления серверной функции запроса:


&НаСервереБезКонтекста
Функция ПолучитьСписокДляВыбора(Знач ТекстПоиска, Знач ТокенАвторизации)
    
    Результат = Новый Массив;
    
    HTTPЗапрос = Новый HTTPЗапрос();
    HTTPЗапрос.АдресРесурса = "/api/v2/suggest/party";
    HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/xml");
    HTTPЗапрос.Заголовки.Вставить("Accept", "application/xml");
    HTTPЗапрос.Заголовки.Вставить("Authorization", "Token " + ТокенАвторизации); 
    HTTPЗапрос.УстановитьТелоИзСтроки("<req><query>" + ТекстПоиска + "</query></req>"); 
    
    Соединение = Новый HTTPСоединение("dadata.ru",,,,,, Новый ЗащищенноеСоединениеOpenSSL);
    ОтветHTTP = Соединение.ОтправитьДляОбработки(HTTPЗапрос);
    
    Если ОтветHTTP.КодСостояния = 200 Тогда
        ЧтениеXML = Новый ЧтениеXML;
        ЧтениеXML.УстановитьСтроку(ОтветHTTP.ПолучитьТелоКакСтроку());
        ЧтениеXML.ПерейтиКСодержимому();
        
        ОбъектXDTO = ФабрикаXDTO.ПрочитатьXML(ЧтениеXML);
        ЧтениеXML.Закрыть();
        
        Если ОбъектXDTO.Свойства().Получить("suggestions") <> Неопределено Тогда
            Если ТипЗнч(ОбъектXDTO.suggestions) = Тип("СписокXDTO") Тогда
                Для Каждого ЭлементXDTO Из ОбъектXDTO.suggestions Цикл
                    Результат.Добавить(Строка(ЭлементXDTO.value));
                КонецЦикла;
            ИначеЕсли ТипЗнч(ОбъектXDTO.suggestions) = Тип("ОбъектXDTO") Тогда
                Результат.Добавить(Строка(ОбъектXDTO.suggestions.value));
            КонецЕсли;
        КонецЕсли; 
    КонецЕсли;
    
    Возврат Результат;
    
КонецФункции

Шаг 2. Использование стандартного механизма ДанныеВыбора

Разберем, как передавать сформированный список подсказок пользователю без сброса текста. Вместо ручной работы с Элемент.СписокВыбора платформа предоставляет параметр события ДанныеВыбора.

Выполним следующие действия в обработчике события АвтоПодбор:

  1. Проверяем минимальную длину введенной строки (например, от 3 символов), чтобы избежать лишних сетевых вызовов.
  2. Инициализируем коллекцию СписокЗначений и помещаем ее в параметр ДанныеВыбора.
  3. Устанавливаем параметр СтандартнаяОбработка = Ложь, сообщая платформе, что список подсказок сформирован программно.
  4. Используем параметр Ожидание = Истина, чтобы платформа отправляла запрос только после небольшой паузы в наборе текста пользователем.

Посмотрим на реализацию клиентского обработчика:


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

Шаг 3. Настройка свойств элемента формы в конфигураторе

Проанализируем свойства поля ввода в палитре свойств, которые влияют на ввод текста:

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

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

← На главную