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