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