Зачем нужно событие ИзменениеТекстаРедактирования для поля ввода строки?

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

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

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

Разберем физику процесса: почему стирается или сбрасывается текст?

Выясним причину, по которой обычное чтение или минимальный анализ параметра Текст в обработчике события ломает процесс ввода. Дело в том, что событие ИзменениеТекстаРедактирования срабатывает на каждое изменение текста в поле ввода пользователем. Если внутри обработчика мы пытаемся изменить значение другого реквизита формы или как-то повлиять на состояние элементов (например, сделать видимым или доступным какой-то элемент, изменить высоту поля, заполнить вспомогательный реквизит), платформа инициирует принудительное обновление и перерисовку управляемой формы.

Во время перерисовки формы система пытается актуализировать данные во всех полях. Поведение поля ввода в этот момент регулируется важнейшим свойством — ОбновлениеТекстаРедактирования (EditTextUpdate):

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

Ограничения платформы: неявные серверные вызовы

Начиная с современных версий платформы 1С:Предприятие 8.3 (активно фиксируется начиная с релиза 8.3.15), в синтакс-помощнике появилось жесткое предупреждение: в обработчике события ИзменениеТекстаРедактирования запрещено использовать серверные методы с директивой компиляции &НаСервере, а также изменять свойства, которые могут привести к серверному вызову.

Если нарушить это правило, платформа сгенерирует исключение или заблокирует интерфейс. Но опасность кроется в неявных вызовах. К ним относятся:

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

Как правильно реализовать серверные вызовы при вводе (Паттерн Debounce)

Чтобы не перегружать сервер частыми запросами при вводе каждой буквы и обойти ограничение на контекстные вызовы, мы можем запускать серверную процедуру с небольшой задержкой (например, 0.3 - 0.5 секунды) после того, как пользователь приостановил ввод. Каждое нажатие клавиши будет сбрасывать таймер и запускать его заново.

Посмотрим на пример реализации такого механизма. Допустим, нам необходимо динамически менять высоту многострочного поля ввода в зависимости от количества введенного текста (символов перевода строки). Разберем этот код по шагам:


&НаКлиенте
ПеременныеФормы = Новый Структура("КоличествоСтрок, ТекстДляАнализа");

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

&НаКлиенте
Процедура ВыполнитьАнализТекста() Экспорт
    
    Текст = ПеременныеФормы.ТекстДляАнализа;
    СтрДлинаТекста = СтрДлина(Текст);
    СчетчикПереносов = 0;
    
    // Подсчитываем количество символов перевода строки (ПС)
    Для СимволНомер = 1 По СтрДлинаТекста Цикл
        Если Сред(Текст, СимволНомер, 1) = Символы.ПС Тогда
            СчетчикПереносов = СчетчикПереносов + 1;
        КонецЕсли;
    КонецЦикла;
    
    // Динамически управляем высотой элемента на клиенте
    НоваяВысота = СчетчикПереносов + 1;
    Если Элементы.Реквизит1.Высота <> НоваяВысота Тогда
        Элементы.Реквизит1.Высота = НоваяВысота;
    КонецЕсли;
    
КонецПроцедуры

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

Практические сценарии использования события

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

Сценарий 1: Очистка или сброс зависимых списков и фильтров при изменении поля

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

Рассмотрим пример кода:


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

Сценарий 2: Быстрое открытие шаблонов при начале ввода

Очень удобный сценарий для текстовых полей (например, «Комментарий» или «Содержание»). Когда пользователь активирует пустое поле и вводит первый символ, мы можем сразу открыть ему список предопределенных шаблонов или популярных фраз, чтобы ускорить заполнение формы.

Проанализируем пример такой реализации:


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

Сценарий 3: Принудительное приведение к верхнему регистру (автоматический Caps Lock)

В некоторых задачах требуется, чтобы вводимый текст (например, артикул, VIN-код автомобиля или серия паспорта) всегда состоял из заглавных букв латиницы или кириллицы. Мы можем на лету переводить вводимые символы в верхний регистр. Для этого обязательно нужно установить свойство ОбновлениеТекстаРедактирования в значение Не использовать.


&НаКлиенте
Процедура КодМашиныИзменениеТекстаРедактирования(Элемент, Текст, СтандартнаяОбработка)
    
    // Преобразуем набранный текст к верхнему регистру
    ТекстВерхнийРегистр = ВРег(Текст);
    
    // Если текст изменился, заменяем его в поле ввода
    Если Текст <> ТекстВерхнийРегистр Тогда
        Текст = ТекстВерхнийРегистр;
    КонецЕсли;
    
КонецПроцедуры

Резюме и правила безопасной работы

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

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

← На главную