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

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

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

Причина проблемы: несоответствие типов данных

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


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

&НаКлиенте
Процедура ParentCompanyАвтоПодбор(Элемент, Текст, ДанныеВыбора, ПараметрыПолученияДанных, Ожидание, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;
    ДанныеВыбора = ParentCompanyАвтоПодборНаСервере(Текст, Объект.Владелец);
КонецПроцедуры

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

Главное правило: для полей ссылочного типа в свойство Значение элемента списка значений необходимо передавать ссылку (СправочникСсылка), а текстовое представление помещать в свойство Представление.

Решение 1. Исправление обработчика автоподбора

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


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

Теперь в свойстве Значение содержится ссылка на элемент справочника, и при выборе строки из подсказки автоподбора значение корректно запишется в связанный реквизит формы.

Решение 2. Штатный декларативный метод (Связи параметров выбора)

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

Разберем по шагам, как настроить фильтрацию без единой строчки кода:

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

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

  1. При быстром автоподборе по строке при вводе текста.
  2. В выпадающем списке недавней истории выбора.
  3. При нажатии на кнопку выбора (троеточие) — форма выбора подчиненного справочника откроется с уже установленным жестким отбором по владельцу.

Решение 3. Обработка получения данных выбора в модуле менеджера

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

Рассмотрим реализацию события ОбработкаПолученияДанныхВыбора в модуле менеджера справочника ПокупателиКомпаний:


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

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

Такой подход обеспечивает единую точку бизнес-логики и избавляет от необходимости дублировать код на различных формах документов и справочников.

Решение 4. Отбор при нажатии кнопки выбора (троеточие)

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


&НаКлиенте
Процедура ParentCompanyНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    ПараметрыОтбора = Новый Структура("Владелец", Объект.Владелец);
    ПараметрыФормы = Новый Структура("Отбор", ПараметрыОтбора);
    
    // Третьим параметром передаем сам Элемент - тогда форма выбора автоматически вернет значение в это поле
    ОткрытьФорму("Справочник.ПокупателиКомпаний.ФормаВыбора", ПараметрыФормы, Элемент);
    
КонецПроцедуры

Передавая Элемент в метод ОткрытьФорму, мы избавляемся от необходимости реализовывать обработчик ОбработкаВыбора вручную — платформа самостоятельно обработает оповещение о выборе и заполнит реквизит формы.

← На главную