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