При разработке интерактивных интерфейсов в среде 1С:Предприятие (например, встроенных чатов, панелей мониторинга заказов или оперативных лент сообщений) часто применяется периодический опрос базы данных с помощью механизма ПодключитьОбработчикОжидания. Однако разработчики нередко сталкиваются с неприятным поведением: пользователь начинает набирать сообщение в поле ввода, но в момент очередного срабатывания фонового таймера набранный текст внезапно исчезает, а курсор сбрасывается.
Разберем детально, почему платформа 1С ведет себя подобным образом и какими способами можно гарантированно сохранить вводимые пользователем данные.
Выясним внутреннюю механику работы управляемых форм. В управляемом интерфейсе 1С при изменении любого реквизита формы запускается процесс синхронизации данных модели с элементами графического интерфейса. Это происходит как при серверных вызовах, так и при простом присвоении значений реквизитам на клиенте.
Пока пользователь набирает текст и еще не нажал клавишу Enter или не перевел фокус на другой элемент (то есть редактирование не завершено), введенные символы находятся во временном буфере — свойстве ТекстРедактирования элемента. Если в этот момент из обработчика ожидания происходит изменение реквизитов формы, платформа форсированно синхронизирует состояние элементов с данными реквизитов, сбрасывая промежуточный текст ввода к исходному сохраненному значению.
Посмотрим на типовой проблемный пример кода:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
ПодключитьОбработчикОжидания("НаличиеНовыхСообщений", 5);
КонецПроцедуры
&НаКлиенте
Процедура НаличиеНовыхСообщений()
// Любая модификация реквизитов формы инициирует перерисовку интерфейса
НовыеСообщения = ПолучитьНовыеСообщенияСервер();
КонецПроцедуры
Наиболее простое и штатное решение проблемы — правильная настройка свойств самого элемента управления ПолеВвода в конфигураторе или программно при создании формы.
Проанализируем доступные варианты свойства элемента ОбновлениеТекстаРедактирования:
Элементы.ИмяЭлемента.ОбновитьТекстРедактирования().Установим для поля ввода сообщения значение свойства ОбновлениеТекстаРедактирования в положение ПриИзмененииЗначения. Это позволит пользователю непрерывно набирать текст, даже если в фоне регулярно обновляются другие переменные формы.
Рассмотрим альтернативный программный подход: перед тем как выполнять тяжелые операции обновления или перезаписывать контекст формы, проверим, не занят ли пользователь набором данных в текущий момент.
Посмотрим на пример реализации логики в обработчике ожидания:
&НаКлиенте
Процедура НаличиеНовыхСообщений()
// Проверяем, находится ли фокус в поле ввода сообщения
Если ЭтаФорма.ТекущийЭлемент = Элементы.ПолеВводаТекстаСообщения Тогда
// Пропускаем такт обновления или откладываем синхронизацию до потери фокуса
Возврат;
КонецЕсли;
ОбновитьДанныеЧатаБезКонтекста();
КонецПроцедуры
При таком подходе фоновое обновление сработает только тогда, когда пользователь не взаимодействует активно с полем ввода. Для фиксации текста можно использовать клиентские события поля ПриИзменении или ОкончаниеВводаТекста.
Проанализируем серверную часть взаимодействия. Вызов процедур с директивой &НаСервере передает на сервер и возвращает обратно весь контекст формы целиком. Это многократно увеличивает риск рассинхронизации данных в полях ввода.
Всегда используем вызовы с директивой &НаСервереБезКонтекста для фонового сбора данных:
&НаСервереБезКонтекста
Функция ПолучитьСписокНовыхСообщенийНаСервере(ИдентификаторПоследнегоСообщения)
// Выполняем легкий запрос к базе данных без передачи контекста формы
Возврат РегистрыСведений.ИсторияСообщений.ПолучитьНовые(ИдентификаторПоследнегоСообщения);
КонецФункции
Если проект требует создания полноценного чата или динамической ленты, рассмотрим более надежные архитектурные механизмы платформы 1С:
ПодключитьОбработчикОжидания с постоянными опросами сервера.