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