При разработке интерфейсов на управляемых формах в 1С:Предприятие часто возникает задача динамического ограничения списка выбора в одном поле в зависимости от значения, установленного в другом поле. Наглядный пример — выбор договора, который должен автоматически фильтроваться по выбранному контрагенту, или выбор номенклатуры, ограниченный определенным производителем. В интерактивном режиме (через конфигуратор) эта связь настраивается очень просто — через свойство Связи параметров выбора. Однако при попытке реализовать ту же логику динамически в коде разработчики часто сталкиваются с ошибкой Недопустимое значение при установке значения атрибута контекста.
В этой статье мы подробно разберем по шагам, почему возникает эта ошибка, как правильно писать программный код для настройки связей параметров выбора, а также рассмотрим важные нюансы работы этого механизма на платформе 1С.
Проанализируем типичный пример кода, который часто приводит к сбою на стороне платформы:
МассивПараметров = Новый Массив;
МассивПараметров.Добавить(Новый ПараметрВыбора("Отбор.Производитель", "Элементы.Товары.ТекущиеДанные.Производитель"));
Элементы.ТоварыНоменклатура.СвязиПараметровВыбора = Новый ФиксированныйМассив(МассивПараметров);
На первый взгляд код выглядит логичным, но при его выполнении система возвращает ошибку о недопустимом значении. Давайте разберемся, почему так происходит.
В платформе 1С существует четкое разделение между статическими и динамическими отборами. Для их реализации используются два совершенно разных класса объектов:
ПараметрВыбора (используется для коллекции ПараметрыВыбора) — предназначен для установки жестких, неизменяемых отборов (например, выбирать только папки или только элементы с определенным предопределенным признаком).СвязьПараметраВыбора (используется для коллекции СвязиПараметровВыбора) — предназначен для создания динамической связи между реквизитами формы в режиме реального времени.В ошибочном коде разработчик попытался поместить объект типа ПараметрВыбора в коллекцию СвязиПараметровВыбора. Платформа строго типизирована в отношении коллекций элементов управления формы, поэтому попытка передать туда массив с объектом неверного типа мгновенно вызывает исключение.
Чтобы исправить ошибку, нам необходимо использовать правильный класс — СвязьПараметраВыбора. Давайте рассмотрим рабочий пример реализации этой логики на сервере. Предположим, мы хотим связать колонку «Номенклатура» в табличной части «Товары» с производителем, выбранным в текущей строке этой же таблицы.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// 1. Создаем стандартный массив для временного хранения связей
МассивСвязей = Новый Массив;
// 2. Инициализируем объект связи параметров выбора с правильным типом
// Первый параметр - имя параметра отбора (например, "Отбор.Производитель")
// Второй параметр - путь к данным на форме, которые будут источником отбора
НоваяСвязь = Новый СвязьПараметраВыбора("Отбор.Производитель", "Элементы.Товары.ТекущиеДанные.Производитель");
// 3. Добавляем созданную связь в наш массив
МассивСвязей.Добавить(НоваяСвязь);
// 4. Переводим массив в фиксированный и присваиваем свойству элемента формы
Элементы.ТоварыНоменклатура.СвязиПараметровВыбора = Новый ФиксированныйМассив(МассивСвязей);
КонецПроцедуры
Обратите внимание на важную деталь: свойство СвязиПараметровВыбора элемента формы принимает исключительно тип ФиксированныйМассив. Передать туда обычный тип Массив напрямую нельзя, его предварительно нужно преобразовать, передав в конструктор Новый ФиксированныйМассив().
Разберем подробнее продвинутые возможности конструктора СвязьПараметраВыбора. Часто разработчики упускают из виду важный третий параметр этого конструктора — РежимИзмененияСвязанногоЗначения.
Этот параметр отвечает за то, что произойдет с зависимым полем, если пользователь изменит значение в основном поле. Например, в поле «Контрагент» выбран «Авангард», а в поле «Договор» — «Основной договор Авангарда». Что произойдет, если пользователь перевыберет контрагента на «Вектор»?
Платформа предлагает два варианта поведения, которые регулируются системным перечислением:
РежимИзмененияСвязанногоЗначения.Очищать (значение по умолчанию) — при изменении основного реквизита зависимое поле будет автоматически очищено. Это наиболее безопасное и правильное поведение с точки зрения бизнес-логики, так как исключает ситуацию, когда в документе остается нерелевантный договор чужого контрагента.РежимИзмененияСвязанногоЗначения.НеИзменять — при изменении основного реквизита значение зависимого поля останется нетронутым. Такое поведение может потребоваться в специфических интерфейсах, где автоматическая очистка мешает пользователю, но требует ручной валидации данных перед записью.Посмотрим на пример использования этого параметра в коде:
НоваяСвязь = Новый СвязьПараметраВыбора(
"Отбор.Владелец",
"Объект.Контрагент",
РежимИзмененияСвязанногоЗначения.Очищать
);
При программной настройке связей критически важно соблюдать два правила: правильно выбирать контекст выполнения кода и корректно формировать строку пути к данным.
Правило 1. Только на сервере. Свойство СвязиПараметровВыбора доступно для записи только в серверном контексте (процедуры с директивами &НаСервере, &НаСервереБезКонтекста или в модуле формы). Попытка выполнить этот код на клиенте (&НаКлиенте) вызовет ошибку компиляции или выполнения.
Правило 2. Корректный синтаксис путей к данным. Строка пути к данным (второй параметр конструктора) должна быть написана без ошибок и соответствовать структуре формы:
Объект. Например: "Объект.Договор", "Объект.Организация"."ВыбранныйСклад"."Элементы.[ИмяТаблицыФормы].ТекущиеДанные.[ИмяКолонки]". Пример: "Элементы.Товары.ТекущиеДанные.Номенклатура". Будьте предельно внимательны к регистру и правильности написания имен элементов формы!Иногда бизнес-логика требует динамического отключения ограничений. Например, при установке определенного флажка («Показывать все договоры») мы должны снять жесткий отбор по контрагенту.
Просто присвоить свойству значение Неопределено или пустую строку не получится — платформа выдаст ошибку. Для полной очистки связей параметров выбора необходимо передать пустой фиксированный массив. Рассмотрим, как это сделать:
&НаСервере
Процедура ОтключитьСвязиПараметровВыбора()
// Присваиваем пустой фиксированный массив для сброса всех связей поля
Элементы.ТоварыНоменклатура.СвязиПараметровВыбора = Новый ФиксированныйМассив(Новый Массив);
КонецПроцедуры
После выполнения этого кода поле ввода вернется к своему стандартному поведению, и при открытии формы выбора пользователю будут доступны все элементы справочника без фильтрации.