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

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

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

Выясним причину сброса текста редактирования

Чтобы понять, почему пропадает текст, проанализируем внутреннюю логику работы управляемого интерфейса 1С:

  1. Клиентская буферизация ввода. Набираемый пользователем текст сначала попадает во временный буфер элемента управления (свойство ТекстРедактирования). Фактическая запись этого текста в реквизит формы происходит только при завершении ввода — например, при нажатии клавиш Enter или Tab, либо при потере полем фокуса ввода (событие ПриИзменении).
  2. Сквозная синхронизация интерфейса. Когда в обработчике ожидания выполняется программное изменение свойств формы (например, ЭтаФорма.Заголовок), изменение других связанных реквизитов или серверный вызов с контекстом (&НаСервере), платформа инициирует обновление интерфейса. При этом элементы формы перерисовываются, а незафиксированный буфер активного поля ввода принудительно перезаписывается текущим значением реквизита.

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

Самый простой и правильный путь — изменить поведение самого поля ввода в свойствах элемента управляемой формы.

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

  1. Откроем форму в конфигураторе и выберем проблемный элемент управления (поле ввода).
  2. В палитре свойств найдем параметр Обновление текста редактирования (ОбновлениеТекстаРедактирования).
  3. Установим значение При изменении значения (в программном коде соответствует системному перечислению РежимОбновленияТекстаРедактирования.ПриИзмененииЗначения).

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

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

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

Разберем пример реализации такой проверки:


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

Способ 3. Перехват ввода через событие «ИзменениеТекстаРедактирования»

Если требуется гарантированно сохранить вводимый текст или временно приостановить таймер на период редактирования, используем расширение поля ввода и событие ИзменениеТекстаРедактирования.

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


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

&НаКлиенте
Процедура ПослеВводаТекста(Результат, ДополнительныеПараметры) Экспорт
    
    Если Результат <> Неопределено Тогда
        Объект.Комментарий = Результат;
    КонецЕсли;
    
    // Возобновляем работу таймера
    ПодключитьОбработчикОжидания("ОбработчикТаймера", 10);
    
КонецПроцедуры

Способ 4. Альтернативные методы вывода динамической информации

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

  1. Использование поля HTML-документа. Создадим на форме элемент ПолеHTMLДокумента. Таймер и визуальное обновление счетчиков можно реализовать на языке JavaScript внутри самого HTML-контейнера. Это изолирует динамику от контекста формы 1С и полностью исключает перерисовку реквизитов.
  2. Вызовы без контекста. Если расчет требует обращения к серверу, используем исключительно директиву &НаСервереБезКонтекста. При таком вызове на сервер не передается вся форма, а ответ не вызывает автоматическую сквозную пересинхронизацию всех полей.
  3. Системная панель состояния. Для вывода служебных статусов и времени вместо изменения заголовка формы можно применять метод Состояние() или ПоказатьОповещениеПользователя().
← На главную