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