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