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

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

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

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

Причина поведения платформы 1С

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

Пока пользователь набирает текст и еще не нажал клавишу Enter или не перевел фокус на другой элемент (то есть редактирование не завершено), введенные символы находятся во временном буфере — свойстве ТекстРедактирования элемента. Если в этот момент из обработчика ожидания происходит изменение реквизитов формы, платформа форсированно синхронизирует состояние элементов с данными реквизитов, сбрасывая промежуточный текст ввода к исходному сохраненному значению.

Посмотрим на типовой проблемный пример кода:


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    ПодключитьОбработчикОжидания("НаличиеНовыхСообщений", 5);
КонецПроцедуры

&НаКлиенте
Процедура НаличиеНовыхСообщений()
    // Любая модификация реквизитов формы инициирует перерисовку интерфейса
    НовыеСообщения = ПолучитьНовыеСообщенияСервер();
КонецПроцедуры

Способ 1. Настройка свойства «ОбновлениеТекстаРедактирования»

Наиболее простое и штатное решение проблемы — правильная настройка свойств самого элемента управления ПолеВвода в конфигураторе или программно при создании формы.

Проанализируем доступные варианты свойства элемента ОбновлениеТекстаРедактирования:

  1. Авто — платформенное поведение по умолчанию, приводящее к сбросу незафиксированного текста при любых обновлениях данных формы.
  2. ПриИзмененииЗначения — платформа обновляет видимый текст в поле ввода только тогда, когда действительно изменяется значение связанного с ним реквизита. Незавершенный ввод пользователя при изменении сторонних реквизитов не затирается.
  3. НеИспользовать — полное отключение автоматического обновления текста редактирования из связанных данных. При необходимости принудительного обновления текста из кода вызывается метод Элементы.ИмяЭлемента.ОбновитьТекстРедактирования().

Установим для поля ввода сообщения значение свойства ОбновлениеТекстаРедактирования в положение ПриИзмененииЗначения. Это позволит пользователю непрерывно набирать текст, даже если в фоне регулярно обновляются другие переменные формы.

Способ 2. Проверка активного элемента перед обновлением данных

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

Посмотрим на пример реализации логики в обработчике ожидания:


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

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

Способ 3. Переход на бесконтекстные вызовы и оптимизация архитектуры

Проанализируем серверную часть взаимодействия. Вызов процедур с директивой &НаСервере передает на сервер и возвращает обратно весь контекст формы целиком. Это многократно увеличивает риск рассинхронизации данных в полях ввода.

Всегда используем вызовы с директивой &НаСервереБезКонтекста для фонового сбора данных:


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

Альтернативные архитектурные решения для чатов и лент событий

Если проект требует создания полноценного чата или динамической ленты, рассмотрим более надежные архитектурные механизмы платформы 1С:

  1. Система взаимодействия 1С — штатный механизм платформы, работающий по Push-технологии. Он доставляет сообщения в реальном времени и избавляет от необходимости использовать ПодключитьОбработчикОжидания с постоянными опросами сервера.
  2. Отображение переписки через элемент «ПолеHTMLДокумента» — вывод истории диалога через веб-разметку. Добавление новых сообщений выполняется точечной вставкой в DOM-дерево страницы через JavaScript. Это полностью исключает обращение к реквизитам самой формы 1С и гарантирует стабильность соседних полей ввода.
  3. Использование динамического списка — если сообщения сохраняются в таблицу базы данных, для их отображения оптимально применить динамический список. Автоматическое фоновое обновление динамического списка изолировано и не влияет на поля редактирования управляемой формы.
← На главную