Как реализовать ввод текста в поле 1С с подсказками без выделения всей строки

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

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

Разбор проблемы: почему стандартные методы не работают

Проанализируем ситуацию. Когда мы используем событие АвтоПодборТекста, платформа ожидает, что выбранное значение полностью заменит введенный текст. Если мы пытаемся вмешаться в процесс через событие ОбработкаВыбора, возникают следующие сложности:

  1. При установке СтандартнаяОбработка = Ложь мы берем управление на себя, но платформа все равно выполняет внутренние алгоритмы отрисовки фокуса после завершения кода обработчика.
  2. Метод УстановитьГраницыВыделения часто игнорируется, так как вызывается слишком рано — до того, как платформа окончательно «успокоит» элемент управления после выбора из списка.
  3. Свойство ОбновлениеТекстаРедактирования по умолчанию стоит в значении Авто, что заставляет систему принудительно синхронизировать визуальное отображение с реквизитом, вызывая выделение всего содержимого.

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

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

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

  1. В свойствах элемента формы (Поле ввода) установим параметр ОбновлениеТекстаРедактирования в значение Не использовать.
  2. Чтобы текст на форме все же обновлялся при открытии или программном изменении, нам придется вызывать обновление принудительно.

В модуле формы при открытии пропишем следующий код:


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    Элементы.ИмяВашегоПоляВвода.ОбновитьТекстРедактирования();
КонецПроцедуры

Это позволит платформе «забыть» о необходимости выделять текст при каждом изменении реквизита, так как автоматическая синхронизация отключена.

Способ 2. Контекстный серверный вызов для сброса состояния

Выясним интересную особенность: выполнение контекстного серверного вызова внутри обработчика события ИзменениеТекстаРедактирования или ОбработкаВыбора заставляет клиентское приложение «перерисовать» состояние элементов формы. Это часто приводит к тому, что нежелательное выделение текста пропадает само собой.

Посмотрим на пример реализации в событии ИзменениеТекстаРедактирования:


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

&НаСервере
Процедура СброситьВыделениеНаСервере()
    // Здесь может быть пусто, сам факт вызова контекста формы решает проблему
КонецПроцедуры

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

Способ 3. Прямое управление границами выделения в ОбработкеВыбора

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


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

Важный нюанс: В некоторых версиях платформы УстановитьГраницыВыделения сработает только в том случае, если реквизит формы был изменен на сервере. Поэтому в ряде случаев присвоение ТекстВвода = ТекстВвода + ... лучше вынести в серверную процедуру.

Способ 4. Использование обработчика ожидания (Advanced)

Если ни один из вышеперечисленных способов не помогает (например, в веб-клиенте), проанализируем асинхронный подход. Проблема в том, что 1С выделяет текст сразу после завершения кода ОбработкаВыбора. Мы можем обмануть систему, вызвав установку курсора через ничтожно малый промежуток времени.


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

&НаКлиенте
Процедура УстановитьКурсорВКонецПоля()
    Элемент = Элементы.ИмяПоляВвода;
    Позиция = СтрДлина(ТекстВвода) + 1;
    Элемент.УстановитьГраницыВыделения(Позиция, Позиция);
КонецПроцедуры

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

Резюме

Для достижения комфортного ввода текста без «прыгающего» выделения мы рекомендуем комбинировать подходы. Начните с установки ОбновлениеТекстаРедактирования в значение Не использовать. Если этого недостаточно, используйте метод с СтандартнаяОбработка = Ложь в событии ОбработкаВыбора совместно с явной установкой границ выделения. Помните, что поведение элементов управления может незначительно отличаться между тонким и веб-клиентом, поэтому всегда тестируйте интерфейсные решения в обоих режимах.

← На главную