Почему не отображается список выбора в обработчике ОкончаниеВводаТекста в управляемых формах 1С?

Программист IT и автоматизация бизнеса
← На главную

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

Анализ проблемы: почему прерывается стандартный механизм

Событие ОкончаниеВводаТекста предназначено для того, чтобы программа могла предложить пользователю список возможных значений после того, как он закончил печатать (например, нажал Enter, Tab или перевел фокус). Однако управляемое приложение работает по специфическим правилам взаимодействия клиента и сервера. Рассмотрим основные причины, по которым платформа может «молча» закрыть список выбора:

  1. Контекстный серверный вызов: Если внутри обработчика вызывается процедура или функция с директивой &НаСервере, платформа передает на сервер весь контекст формы (значения всех реквизитов). После выполнения кода форма возвращается на клиент и «обновляется». Это обновление часто сбрасывает интерактивное состояние поля ввода, и список выбора просто не успевает отрисоваться.
  2. Изменение данных формы: Если в момент ввода текста программно изменить значение любого реквизита формы (например, через процедуру ОчисткаПолей()), система считает текущую операцию ввода завершенной или неактуальной, что приводит к закрытию всех вспомогательных окон подбора.
  3. Стандартная обработка: По умолчанию платформа пытается сама найти значение. Если мы формируем свой список, мы обязаны явно сообщить об этом системе.

Решение 1: Использование внеконтекстных вызовов

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

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


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

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

Решение 2: Управление стандартной обработкой

Выясним, как правильно передать управление платформе. Чтобы 1С поняла, что нужно показать именно ваш СписокЗначений, необходимо установить параметр СтандартнаяОбработка в значение Ложь. Это нужно делать только в том случае, если вы действительно нашли данные.

Разберем обновленный клиентский обработчик:


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

Решение 3: Проблема модификации данных формы

Рассмотрим ситуацию с процедурой ОчисткаПолей(). Если эта процедура очищает другие реквизиты объекта или формы (например, Объект.Контрагент = Неопределено;), то в момент выполнения этой строки платформа фиксирует изменение данных. Любое изменение данных формы во время интерактивного ввода приводит к «схлопыванию» выпадающих списков.

Как поступить правильно:

  1. Вынесите очистку зависимых полей в событие ПриИзменении самого поля ввода. Оно сработает уже после того, как пользователь выберет значение из списка.
  2. Если очистка необходима именно в момент ввода, убедитесь, что она не затрагивает реквизиты, связанные с текущим элементом управления, и не вызывает серверных контекстных действий.

Проанализируем опасный код, который «убивает» обработчик:


// ТАК ДЕЛАТЬ НЕЛЬЗЯ внутри ОкончаниеВводаТекста
&НаКлиенте
Процедура ОчисткаПолей()
    ЭтаФорма.КонтактноеЛицо = ПредопределенноеЗначение("Справочник.КонтактныеЛица.ПустаяСсылка");
    ЭтаФорма.Комментарий = ""; // Изменение реквизитов формы сбрасывает состояние списка выбора!
КонецПроцедуры

Альтернативный подход: Событие АвтоПодбор

Если ваша задача — реализовать удобный поиск (например, по номеру телефона или части наименования), мы рекомендуем рассмотреть событие АвтоПодбор. В отличие от ОкончаниеВводаТекста, оно срабатывает «на лету» по мере набора текста пользователем. Это более современный и отзывчивый интерфейсный подход.

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


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

Этот метод более стабилен, так как платформа специально оптимизирована для формирования ДанныхВыбора именно в этом событии.

Итоги и рекомендации

Для того чтобы ваш обработчик события ОкончаниеВводаТекста работал корректно, придерживайтесь следующих правил:

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

← На главную