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