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