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