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