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

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

При разработке на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда код, идеально работающий в тонком клиенте, ведет себя непредсказуемо в веб-клиенте. Одной из таких классических проблем является работа с объектом ТабличныйДокумент. Рассмотрим ситуацию: у нас есть сформированный документ, который мы пытаемся вывести пользователю на форму, но вместо заполненных данных в браузере видим пустой лист, хотя в тонком клиенте всё отображается корректно. Разберем по шагам, почему это происходит и как правильно организовать вывод данных.

Анализ проблемы: разница между тонким и веб-клиентом

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


&НаКлиенте
Процедура ОтобразитьДокумент(ТД)
    Если ТипЗнч(ТД) = Тип("ТабличныйДокумент") Тогда 
        #Если ВебКлиент Тогда
            // Попытка присвоения в веб-клиенте
            ТабличныйДокумент = ТД;
        #Иначе
            // Попытка присвоения в тонком клиенте
            ТабличныйДокумент = ТД;
        #КонецЕсли        
    КонецЕсли;
КонецПроцедуры

В тонком клиенте это работает, так как приложение имеет прямой доступ к памяти и объектам операционной системы. Однако веб-клиент — это, по сути, среда JavaScript внутри браузера. Здесь объект ТабличныйДокумент проходит через процесс сериализации. Когда мы просто присваиваем объект на клиенте, платформа не всегда инициирует полноценное обновление графического интерфейса в браузере. Выясним причину: браузеру недостаточно просто "знать", что переменная изменилась, ему нужно получить сформированный HTML/CSS пакет для отрисовки ячеек, чего при простом клиентском присваивании может не произойти.

Решение №1: Принудительное присваивание на сервере

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

Рассмотрим правильную структуру вызова:


&НаКлиенте
Процедура ВыполнитьВывод()
    // Предположим, ТД_Сформированный уже получен
    ТДСервер(ТД_Сформированный);
КонецПроцедуры

&НаСервере
Процедура ТДСервер(ТД)
    // Реквизит формы "ТабличныйДокумент" заполняется на сервере
    ЭтаФорма.ТабличныйДокумент = ТД;     
КонецПроцедуры

Этот метод гарантирует результат, но имеет один существенный минус, упомянутый автором вопроса: низкая скорость работы. Это происходит из-за того, что при вызове &НаСервере передается весь контекст формы (все реквизиты, данные и состояние элементов управления), что в веб-клиенте создает большой трафик между браузером и сервером приложений.

Решение №2: Оптимизация через временное хранилище

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

  1. Сформируем табличный документ на сервере (без контекста формы).
  2. Поместим его во временное хранилище и получим адрес.
  3. На клиенте вызовем серверную процедуру, передав только адрес строки.
  4. На сервере (с контекстом) получим объект по адресу и присвоим его реквизиту формы.

Посмотрим на пример кода:


&НаСервереБезКонтекста
Функция СформироватьТДНаСервере()
    ТД = Новый ТабличныйДокумент;
    // ... логика заполнения документа ...
    Возврат ПоместитьВоВременноеХранилище(ТД, Новый УникальныйИдентификатор);
КонецФункции

&НаСервере
Процедура ЗаполнитьТДИзХранилища(Адрес)
    // Получаем объект и присваиваем его реквизиту формы
    ТД_ИзХранилища = ПолучитьИзВременногоХранилища(Адрес);
    Если ТипЗнч(ТД_ИзХранилища) = Тип("ТабличныйДокумент") Тогда
        ЭтаФорма.РезультатТабличныйДокумент = ТД_ИзХранилища;
    КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура КомандаСформировать(Команда)
    Адрес = СформироватьТДНаСервере();
    ЗаполнитьТДИзХранилища(Адрес);
КонецПроцедуры

Такой подход значительно ускоряет работу в веб-клиенте, так как мы не передаем тяжелый объект ТабличныйДокумент в параметрах вызова, а работаем с короткой строкой-ссылкой.

Решение №3: Использование метода Вывести()

Иногда проблему обновления визуального состояния в веб-клиенте можно решить без полной перезаписи объекта. Выясним, как работает метод Вывести(). Если у вас уже есть пустой реквизит формы типа ТабличныйДокумент, вместо прямого присваивания можно попробовать использовать метод вывода документа в документ.

Проанализируем ситуацию: метод Вывести() заставляет движок платформы зафиксировать изменения в структуре документа. Хотя это чаще используется для построчного формирования, в случае с веб-клиентом это может послужить "триггером" для обновления DOM-модели в браузере.


&НаСервере
Процедура ВывестиТДНаСервере(ВходящийТД)
    ЭтаФорма.РеквизитТабличныйДокумент.Очистить();
    ЭтаФорма.РеквизитТабличныйДокумент.Вывести(ВходящийТД);
КонецПроцедуры

Почему ОбновитьОтображениеДанных() не помогает?

Многие разработчики пытаются использовать метод ОбновитьОтображениеДанных(), чтобы "протолкнуть" изменения из памяти на экран. Однако в случае с веб-клиентом и табличным документом это часто оказывается бесполезным. Проблема в том, что ОбновитьОтображениеДанных() обновляет визуальное состояние элементов, связанных с данными, которые уже синхронизированы между клиентом и сервером. Если само присваивание ТабличныйДокумент = ТД на клиенте не привело к синхронизации внутреннего состояния объекта с сервером (что является особенностью веб-клиента), то обновлять визуально просто нечего — платформа "считает", что документ пуст.

Подведем итоги

Для стабильной и быстрой работы с табличными документами в веб-интерфейсе 1С следует придерживаться следующих правил:

Соблюдение этих архитектурных принципов позволит вашим решениям работать одинаково быстро и корректно как в тяжелом приложении, так и в любом современном браузере через веб-клиент.

← На главную