Как изменить данные в строке табличной части в управляемом режиме 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При переходе с обычных форм на управляемые многие разработчики сталкиваются с проблемой: привычный код для изменения реквизитов строки табличной части перестает работать. В обычном приложении мы могли напрямую обращаться к реквизитам через точку, например: ТекущиеДанные.Вагон.ПринадлежностьВагона. Однако в управляемом режиме (тонкий клиент) прямое обращение к реквизитам ссылки через точку невозможно, так как это вызывает неявное обращение к базе данных, которое запрещено на стороне клиента.

В этой статье мы подробно разберем, как правильно изменять данные текущей строки в управляемом режиме, рассмотрим различные способы оптимизации серверных вызовов и выясним, как сделать интерфейс максимально отзывчивым.

Причина проблемы: Тонкий клиент и обращения через точку

Рассмотрим стандартную ситуацию. У нас есть документ с табличной частью Вагоны. При выборе значения в колонке Вагон нам нужно автоматически заполнить колонку ПринадлежностьВагона, значение которой хранится в самом справочнике. В управляемом приложении выполнение кода на клиенте ограничено. Когда мы пишем ТекущиеДанные.Вагон, мы получаем ссылку. Ссылка — это лишь идентификатор объекта в базе данных. Чтобы узнать значение реквизита этой ссылки, нужно "заглянуть" в базу, а это прерогатива сервера.

Вариант 1. Использование бесконтекстного серверного вызова

Это наиболее правильный и производительный метод, если в конфигурации не используется БСП (Библиотека стандартных подсистем). Мы создаем на клиенте обработчик события ПриИзменении, который вызывает функцию на сервере без передачи контекста всей формы.

Проанализируем пример кода:


&НаКлиенте
Процедура ВагоныВагонПриИзменении(Элемент)
    
    ТекущиеДанные = Элементы.Вагоны.ТекущиеДанные;
    
    Если ТекущиеДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Проверяем, заполнено ли значение, чтобы не гонять сервер впустую
    Если ЗначениеЗаполнено(ТекущиеДанные.Вагон) Тогда
        ТекущиеДанные.ПринадлежностьВагона = ПолучитьПринадлежностьВагонаНаСервере(ТекущиеДанные.Вагон);
    Иначе
        ТекущиеДанные.ПринадлежностьВагона = ПредопределенноеЗначение("Справочник.ПринадлежностьВагона.ПустаяСсылка");
    КонецЕсли;
    
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьПринадлежностьВагонаНаСервере(Вагон)
    // На сервере обращение через точку разрешено
    Возврат Вагон.ПринадлежностьВагона;
КонецФункции

Важный нюанс: Использование директивы &НаСервереБезКонтекста критически важно для производительности. В этом случае на сервер передается только ссылка Вагон, а не вся форма целиком со всеми данными объекта.

Вариант 2. Использование функций БСП

Если ваша конфигурация разработана на базе БСП, задачу можно решить еще проще. В составе библиотеки есть универсальные функции для получения реквизитов объектов. Разберем, как это выглядит:


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

Этот метод удобен тем, что вам не нужно плодить мелкие серверные функции в модуле формы. Однако помните, что внутри ОбщегоНазначения.ЗначениеРеквизитаОбъекта все равно происходит серверный вызов.

Вариант 3. Контекстный вызов и поиск строки по идентификатору

Иногда логика заполнения строки настолько сложная, что требуется доступ ко многим реквизитам документа. В этом случае используется процедура &НаСервере. Чтобы изменить данные конкретной строки, нам нужно найти её в коллекции Объект.Вагоны по идентификатору.

Посмотрим на алгоритм реализации:

  1. На клиенте получаем идентификатор текущей строки через Элементы.Вагоны.ТекущаяСтрока.
  2. Передаем этот идентификатор в серверную процедуру.
  3. На сервере используем метод НайтиПоИдентификатору().

&НаКлиенте
Процедура ВагоныВагонПриИзменении(Элемент)
    
    ИдентификаторСтроки = Элементы.Вагоны.ТекущаяСтрока;
    Если ИдентификаторСтроки <> Неопределено Тогда
        ЗаполнитьДанныеСтрокиНаСервере(ИдентификаторСтроки);
    КонецЕсли;
    
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьДанныеСтрокиНаСервере(ИдентификаторСтроки)
    
    // Находим строку в данных формы
    СтрокаТаблицы = Объект.Вагоны.НайтиПоИдентификатору(ИдентификаторСтроки);
    
    Если СтрокаТаблицы <> Неопределено Тогда
        // Здесь мы имеем доступ и к данным строки, и к реквизитам всего Объекта
        СтрокаТаблицы.ПринадлежностьВагона = СтрокаТаблицы.Вагон.ПринадлежностьВагона;
    КонецЕсли;
    
КонецПроцедуры

Как оптимизировать работу и избежать лишних вызовов?

Постоянные обращения к серверу при изменении каждой строки могут замедлить работу пользователя, особенно при "плохом" интернете. Рассмотрим продвинутые методы оптимизации:

1. Получение данных через форму выбора. Мы можем настроить форму выбора справочника Вагоны так, чтобы при выборе элемента она возвращала не только ссылку, но и структуру со всеми необходимыми реквизитами. Это позволит заполнить всю строку на клиенте за один раз без дополнительных обращений к серверу в событии ПриИзменении.

2. Кэширование данных. Если справочник "Принадлежность" небольшой, можно при открытии формы один раз считать его данные в массив или структуру на клиенте. Тогда сопоставление будет происходить мгновенно.

3. Связи параметров выбора. Если поле ПринадлежностьВагона должно просто фильтроваться в зависимости от Вагона, используйте свойство "Связи параметров выбора" в конфигураторе. Это стандартный механизм платформы, не требующий написания кода.

Типичные ошибки, которых стоит избегать

Разберем основные ошибки начинающих разработчиков:

Подводя итог, отметим: работа с данными строки в управляемом режиме требует четкого разделения логики на клиентскую и серверную части. Проанализировав ситуацию, всегда отдавайте предпочтение бесконтекстным вызовам или механизмам возврата данных из формы выбора для обеспечения наилучшего пользовательского опыта.

← На главную