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