Почему в веб-клиенте 1С зацикливается событие ПриАктивизацииСтроки и некорректно открывается форма?

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

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

Особенности диагностики: почему кажется, что серверные процедуры не выполняются

Первое впечатление при возникновении сбоя в веб-клиенте — форма открывается пустой или часть полей не инициализируется, из-за чего возникает подозрение, что обработчик ПриСозданииНаСервере или ПриЧтенииНаСервере пропущен платформой. Дополнительную путаницу вносят особенности взаимодействия клиента и сервера в веб-среде:

  1. Нестабильность отладки по HTTP. В веб-клиенте точки останова на стороне сервера могут срабатывать нестабильно в зависимости от настроек веб-сервера и версии платформы.
  2. Буферизация сообщений. Функция Сообщить(), вызванная на сервере, не выводит текст в веб-клиент мгновенно. Платформа накапливает пакеты сообщений и отправляет их клиенту порциями, поэтому при зависании или сбое браузера окно сообщений может остаться пустым.

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


&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
    ЭтаФорма.Заголовок = ЭтаФорма.Заголовок + " [ПриЧтении] " + ТекущаяДата();
КонецПроцедуры

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    ЭтаФорма.Заголовок = ЭтаФорма.Заголовок + " [ПриСоздании] " + ТекущаяДата();
КонецПроцедуры

&НаКлиенте
Процедура ПриОткрытии(Отказ)
    ЭтаФорма.Заголовок = ЭтаФорма.Заголовок + " [ПриОткрытии] " + ТекущаяДата();
КонецПроцедуры

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

Причины зацикливания события ПриАктивизацииСтроки в веб-клиенте

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

  1. Поведение тонкого клиента. Нативные компоненты операционной системы оптимизируют перерисовку окон: скрытие или показ отдельного элемента управления выполняется локально и не сбрасывает фокус текущей строки таблицы.
  2. Поведение веб-клиента. В браузере динамическое изменение свойства Видимость вызывает полную перестройку ветки DOM-дерева и перерасчет геометрии формы. В процессе перерисовки табличная часть временно теряет и восстанавливает фокус на активной строке. Движок браузера расценивает это как повторный выбор строки пользователем и снова генерирует системное событие активизации.

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

Рассмотрим проверенные практические способы устранения этой ошибки.

Способ 1. Разрыв цепочки событий через обработчик ожидания

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


&НаКлиенте
Процедура ТаблицаСписокПриАктивизацииСтроки(Элемент)
    // Подключаем однократный обработчик с минимальной задержкой
    ПодключитьОбработчикОжидания("ОбновитьОтображениеЭлементов", 0.1, Истина);
КонецПроцедуры

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

    // Управляем интерфейсом вне прямого потока событий таблицы
    Элементы.ГруппаДополнительно.Видимость = СтрокаТаблицы.РазныеСроки;
КонецПроцедуры

В данном сценарии событие ПриАктивизацииСтроки завершается мгновенно, браузер завершает расчет выделения строки, и лишь затем управление передается процедуре обновления. Зацикливание полностью исключается.

Способ 2. Блокировка рекурсии с проверкой смены строки

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


&НаКлиенте
Перем ПредыдущаяСтрокаТаблицы;

&НаКлиенте
Процедура ТаблицаСписокПриАктивизацииСтроки(Элемент)
    ТекущаяСтрока = Элементы.ТаблицаСписок.ТекущаяСтрока;
    
    // Если событие вызвано повторно для той же строки — выходим
    Если ТекущаяСтрока = ПредыдущаяСтрокаТаблицы Тогда
        Возврат;
    КонецЕсли;
    
    ПредыдущаяСтрокаТаблицы = ТекущаяСтрока;
    
    СтрокаДанных = Элементы.ТаблицаСписок.ТекущиеДанные;
    Если СтрокаДанных <> Неопределено Тогда
        Элементы.ПолеСрок.Видимость = СтрокаДанных.РазныеСроки;
    КонецЕсли;
КонецПроцедуры

Благодаря проверке ТекущаяСтрока = ПредыдущаяСтрокаТаблицы повторные импульсы, возникающие при перестроении DOM в веб-клиенте, сразу пресекаются оператором Возврат.

Способ 3. Проверка изменения текущего значения свойства

Частая ошибка разработчиков — безусловная перезапись свойств интерфейса на каждом шаге. Даже если строка изменилась, требуемое состояние видимости элементов могло остаться прежним. Исключим лишние перерисовки простой проверкой:


&НаКлиенте
Процедура ОбновитьВидимостьПоля(ЭлементФормы, Знач НоваяВидимость)
    Если ЭлементФормы.Видимость <> НоваяВидимость Тогда
        ЭлементФормы.Видимость = НоваяВидимость;
    КонецЕсли;
КонецПроцедуры

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

Альтернативные варианты реализации интерфейса

Чтобы приложение гарантированно стабильно работало в любых браузерах, проанализируем альтернативные способы адаптации интерфейса:

  1. Замена свойства Видимость на Доступность или ТолькоПросмотр. Свойства Доступность и ТолькоПросмотр блокируют редактирование реквизитов, но не удаляют теги из структуры DOM и не вызывают пересчет размеров окружающей таблицы, предотвращая сброс фокуса строки.
  2. Применение групп вида «Страницы». Вместо динамического скрытия полей разместим различные наборы реквизитов на вкладках группы типа «Страницы» (с отключенным отображением закладок). В событии активизации строки достаточно программно переключать свойство ТекущаяСтраница: переключение страниц оптимизировано веб-клиентом и не вызывает рекурсивных событий.
← На главную