Как в 1С 8.3 реализовать выпадающий список с возможностью ручного ввода в поле формы

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

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

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

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

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

  1. КнопкаВыпадающегоСписка (DropListButton): Установим значение в Да. Это добавит маленькую стрелку справа от поля, при нажатии на которую будет раскрываться список.
  2. РежимВыбораИзСписка (ListChoiceMode): Установим в значение Нет. Это критически важный момент. Если оставить здесь Да, система заблокирует возможность ручного ввода любого текста, не входящего в список.
  3. РедактированиеТекста (TextEdit): Убедимся, что стоит флаг Да. Это позволит пользователю печатать в поле.

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

Программное заполнение списка выбора

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

Проанализируем пример кода для заполнения списка из запроса:


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

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

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

Использование события АвтоПодбор для динамического поиска

Если данных в справочнике очень много, заполнять весь список выбора сразу неэффективно. Проанализируем более продвинутый метод — использование события АвтоПодбор. Это событие срабатывает, когда пользователь начинает вводить текст в поле.

Рассмотрим, как это реализовать. В свойствах элемента формы найдем событие АвтоПодбор и создадим обработчик:


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

На сервере мы подготовим список значений, которые начинаются с введенного пользователем текста:


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

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

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

Обработка ввода нового значения

Когда мы разрешаем ручной ввод (то есть РежимВыбораИзСписка = Нет), возникает вопрос: что делать, если пользователь ввел текст, которого нет в базе? Если реквизит формы имеет тип Строка, то данные просто запишутся в объект. Однако, если мы работаем со ссылочными типами (например, СправочникСсылка), нам может потребоваться создать новый элемент справочника «на лету».

Разберем, как это сделать в событии ПриИзменении:


&НаСервере
Процедура РеквизитПриИзмененииНаСервере()
    
    // Проверяем, существует ли уже элемент с таким наименованием
    НайденнаяСсылка = Справочники.РФО_Теплоходы.НайтиПоНаименованию(Объект.ИмяРеквизита);
    
    Если НайденнаяСсылка.Пустая() Тогда
        // Если не нашли — создаем новый элемент
        НовыйОбъект = Справочники.РФО_Теплоходы.СоздатьЭлемент();
        НовыйОбъект.Наименование = Объект.ИмяРеквизита;
        НовыйОбъект.Записать();
        
        // Подставляем ссылку на созданный объект
        // Внимание: это сработает, если тип реквизита позволяет хранить ссылку
        // Если тип реквизита "Строка", можно оставить просто текст
    КонецЕсли;

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

Специфика работы с типами данных

Проанализируем ситуацию с типами данных реквизита, так как это часто вызывает путаницу:

Рекомендации по улучшению UX (пользовательского опыта)

Для того чтобы интерфейс был интуитивно понятным, обратим внимание на следующие детали:

Во-первых, используйте свойство ПодсказкаВвода. Напишите там фразу вроде «Выберите из списка или введите вручную». Это снимет вопросы пользователя о том, можно ли печатать в этом поле.

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

В-третьих, проанализируем свойство ОбновлениеТекстаРедактирования. Если вы программно меняете значение поля, это свойство определяет, когда текст в поле ввода обновится. Значение ПриИзменении обычно является оптимальным для большинства задач.

Таким образом, комбинируя свойства КнопкаВыпадающегоСписка, РежимВыбораИзСписка и обработку события АвтоПодбор, мы получаем мощный инструмент для создания удобных и гибких интерфейсов ввода данных в системе 1С:Предприятие 8.3.

← На главную