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

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

Разработчики при проектировании интерфейсов в платформе «1С:Предприятие 8.3» часто сталкиваются с ситуацией, когда один и тот же код ведет себя совершенно по-разному в тонком клиенте и в веб-клиенте. Типичный пример — динамический список, в запросе которого используется вычисляемое поле (например, пометка строк флажками на основе параметров запроса). В тонком клиенте все работает моментально, а в веб-клиенте интерфейс просто «залипает» и не отображает изменения, хотя отладчик показывает, что данные передаются корректно.

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

Суть проблемы: почему «залипают» данные в веб-клиенте?

Рассмотрим классический сценарий. В нашей конфигурации есть динамический список с произвольным запросом. Мы хотим выводить на экран колонку с флажком (булево значение), которая зависит от внешнего параметра. Запрос динамического списка выглядит следующим образом:


ВЫБРАТЬ
    ВЫБОР
        КОГДА Т.Ссылка В (&ВыделенныеОбъекты)
            ТОГДА ИСТИНА
        ИНАЧЕ ЛОЖЬ
    КОНЕЦ КАК ОтображатьНаКарте,
    Т.Ссылка КАК Ссылка,
    Т.КоординатаШирота КАК КоординатаШирота,
    Т.КоординатаДолгота КАК КоординатаДолгота
ИЗ
    Справочник.Объекты КАК Т

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

Давайте разберем техническую причину этого поведения:

  1. Оптимизация DOM и виртуализация строк в веб-клиенте. В отличие от тонкого клиента, который отрисовывает интерфейс через нативные системные компоненты, веб-клиент работает внутри браузера и полностью управляется кодом JavaScript. Для обеспечения высокой производительности движок 1С в веб-клиенте кэширует строки таблиц и минимизирует количество операций с DOM-деревом.
  2. Игнорирование неизмененных объектов. Когда вы передаете новый параметр запроса, сервер честно выполняет SQL-запрос и получает обновленную выборку. Но для веб-клиента сами объекты (ссылки, версии объектов) в базе данных не изменились. Браузерный JS-движок видит, что идентификаторы строк прежние, их версии в БД не поменялись, а значит, с его точки зрения, обновлять визуальное состояние строк не требуется. Изменившееся на сервере виртуальное поле ОтображатьНаКарте просто игнорируется механизмом оптимизации трафика.

Ниже мы подробно рассмотрим несколько способов решения этой проблемы, начиная с самого простого «костыля» и заканчивая архитектурно правильными методиками для веб-клиента.

Решение 1: Сброс кэша через очистку условного оформления (Быстрый обходной путь)

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

Если на вашем списке не настроено критически важное условное оформление, то после установки параметра динамического списка достаточно вызвать следующий код:


// Устанавливаем параметр списка на сервере
Список.Параметры.УстановитьЗначениеПараметра("ВыделенныеОбъекты", НовыйМассивОбъектов);

// Принудительно сбрасываем кэш отображения веб-клиента
Список.УсловноеОформление.Очистить();

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

Решение 2: Деликатное «подмигивание» условным оформлением

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

Рассмотрим пример создания и удаления фиктивного элемента оформления:


// Устанавливаем значение параметра
Список.Параметры.УстановитьЗначениеПараметра("ВыделенныеОбъекты", НовыйМассивОбъектов);

// Добавляем временный неактивный элемент условного оформления для провокации перерисовки
ВременныйЭлемент = Список.УсловноеОформление.Элементы.Добавить();
ВременныйЭлемент.Использование = Ложь;

// Удаляем его, чтобы не засорять коллекцию
Список.УсловноеОформление.Eлементы.Удалить(ВременныйЭлемент);

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

Решение 3: Использование свойства «Использовать всегда»

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

Выполним следующие шаги:

  1. Откройте форму с динамическим списком в конфигураторе.
  2. Перейдите в свойства динамического списка и откройте **«Настройки компоновки данных»** (или зайдите в свойства самого поля в списке выбора).
  3. Найдите ваше вычисляемое поле (в нашем примере это ОтображатьНаКарте), а также поле Ссылка.
  4. Установите для этих полей флажок в свойстве «Использовать всегда».

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

Решение 4: Использование фиктивного параметра в запросе

Еще один надежный способ заставить платформу думать, что данные списка полностью изменились — это использование динамического «шумящего» параметра в запросе. Мы можем добавить в запрос условие, которое логически всегда истинно, но зависит от постоянно меняющегося параметра.

Модифицируем запрос динамического списка:


ВЫБРАТЬ
    ВЫБОР
        КОГДА Т.Ссылка В (&ВыделенныеОбъекты)
            ТОГДА ИСТИНА
        ИНАЧЕ ЛОЖЬ
    КОНЕЦ КАК ОтображатьНаКарте,
    Т.Ссылка КАК Ссылка
ИЗ
    Справочник.Объекты КАК Т
ГДЕ
    &ФиктивныйПараметр = &ФиктивныйПараметр

При каждом изменении параметра &ВыделенныеОбъекты мы также передаем в &ФиктивныйПараметр уникальное значение, например, текущую дату с миллисекундами или новый УникальныйИдентификатор:


Список.Параметры.УстановитьЗначениеПараметра("ВыделенныеОбъекты", НовыйМассивОбъектов);
Список.Параметры.УстановитьЗначениеПараметра("ФиктивныйПараметр", Новый УникальныйИдентификатор());

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

Решение 5: Отказ от расчета флажков в запросе (Best Practice для веб-клиента)

Если вы хотите, чтобы ваше приложение работало в браузере максимально быстро и без лишних нагрузок на сервер СУБД, рекомендуется отказаться от расчета признаков выделения внутри тяжелых SQL-запросов динамического списка.

Рассмотрим более изящное и производительное решение:

  1. В динамическом списке оставьте только выборку основных данных (без конструкции ВЫБОР КОГДА...).
  2. Добавьте в таблицу формы новую колонку с типом Картинка.
  3. В качестве картинки используйте стандартную коллекцию картинок (например, пустой и заполненный флажок).
  4. На клиенте храните массив или соответствие выделенных объектов (например, в переменной модуля формы ВыделенныеОбъектыМассив).
  5. В событии динамического списка ПриВыводеСтроки (или с помощью условного оформления картинок на клиенте) управляйте индексом выводимой картинки. Это позволит избежать лишних серверных вызовов СУБД при каждом клике пользователя.

Используя предложенные методики, вы сможете обеспечить стабильную и предсказуемую работу динамических списков в веб-клиенте «1С:Предприятия», избежав проблем с зависанием интерфейса у конечных пользователей.

← На главную