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