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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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


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

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


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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

← На главную