Фокус на нужное поле, кнопку или строку таблицы: приёмы для управляемых форм 1С 8.3

· 9 мин

Содержание

Чтобы активизировать элемент управляемой формы в 1С 8.3, присвойте его свойству формы ТекущийЭлемент: ТекущийЭлемент = Элементы.Контрагент;. Отдельного метода вроде SetFocus() или Активизировать() у поля нет. Это частое заблуждение тех, кто пришёл из других языков: метод Активизировать() есть у самой формы, и он выводит на передний план окно, а не поле.

В английском синтаксисе то же свойство называется CurrentItem. Работает оно для полей ввода, кнопок и таблиц. Если присваивание есть, а курсор не двигается, почти всегда виновата не строка кода, а окружение: скрытая страница, асинхронный диалог или таблица, где фокус задаётся на трёх уровнях сразу.

Способы программно поставить фокус на элемент формы

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

СпособГде задаётсяКогда подходит
Свойство ТекущийЭлементВ коде, на клиенте или в ПриСозданииНаСервереФокус зависит от условий: новый объект, заполненность реквизитов, режим открытия
Флажок «Активизировать по умолчанию»Палитра свойств элемента в конфигуратореФокус на открытии всегда один и тот же
Порядок элементов в дереве формыРедактор формы, вкладка «Элементы»Нужно поменять порядок перехода по Tab

Свойство ТекущийЭлемент

Самый гибкий вариант. Пример: новый документ открывается на поле контрагента, а записанный — на табличной части.

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

	Если Объект.Ссылка.Пустая() Тогда
		ТекущийЭлемент = Элементы.Контрагент;
	Иначе
		ТекущийЭлемент = Элементы.Товары;
	КонецЕсли;

КонецПроцедуры

Свойство можно и читать. Так проверяют, где сейчас стоит курсор пользователя:

&НаКлиенте
Процедура ПересчитатьВсё(Команда)

	Если ТекущийЭлемент = Элементы.Сумма Тогда
		// пользователь стоит в поле суммы — пересчитываем от неё
	КонецЕсли;

КонецПроцедуры

Мини-кейс: открыть форму на первом незаполненном поле

Частая просьба пользователей: «пусть курсор сразу встаёт туда, что ещё не заполнено». Решается одной процедурой без перебора всех реквизитов — достаточно списка обязательных полей в нужном порядке:

&НаСервере
Процедура АктивизироватьПервоеПустое()

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

	ТекущийЭлемент = Элементы.Товары;

КонецПроцедуры

Вызовите её в конце ПриСозданииНаСервере, после типового заполнения. Здесь имена элементов совпадают с именами реквизитов. Если в вашей форме они различаются, храните пары «реквизит — элемент» в соответствии.

Флажок «Активизировать по умолчанию»

В палитре свойств поля есть флажок АктивизироватьПоУмолчанию. Он говорит платформе, какой элемент получит фокус при открытии формы. Код не нужен.

💡 Если флажок стоит у нескольких элементов, рассчитывать на «правильный» выбор платформы не стоит. Оставьте его у одного.

Порядок обхода и пропуск полей

В управляемой форме фокус по клавише Tab идёт в порядке элементов в дереве формы. Чтобы переставить поле, перетащите его в дереве — отдельного редактора порядка обхода, как в обычных формах, здесь нет.

Свойство ПропускатьПриВводе исключает поле из обхода клавиатурой. Мышью в такое поле попасть можно, из кода через ТекущийЭлемент — тоже.

События, связанные с получением и потерей фокуса

Здесь разработчиков чаще всего ждёт сюрприз. У обычного поля ввода управляемой формы нет событий «получил фокус» и «потерял фокус». Обработчиков с именами вроде ПриПолученииФокуса в палитре свойств поля вы не найдёте.

Что есть вместо них:

  • 🔹 ПриИзменении — срабатывает, когда пользователь изменил значение и ушёл из поля или нажал Enter. Это самое близкое к «потере фокуса», но если значение не менялось, событие не вызывается.
  • 🔹 ОкончаниеВводаТекста — когда ввод текста завершён. Здесь можно перехватить и проверить введённую строку до того, как она станет значением.
  • 🔹 ИзменениеТекстаРедактирования — на каждое изменение текста при включённом свойстве обновления текста. Годится для живого поиска.
  • 🔹 ПриАктивизацииСтроки и ПриАктивизацииПоля — у таблицы формы: пользователь перешёл на другую строку или в другую колонку.
  • 🔹 ПриАктивизации — у поля табличного документа: выделение переместилось на другую ячейку или область.

Если всё-таки нужно знать, куда ушёл курсор

Для обычных полей события нет, поэтому применяют обработчик ожидания. Он раз в полсекунды сравнивает ТекущийЭлемент с запомненным значением:

&НаКлиенте
Перем ПредыдущийЭлемент;

&НаКлиенте
Процедура ПриОткрытии(Отказ)
	ПодключитьОбработчикОжидания("ОтследитьФокус", 0.5);
КонецПроцедуры

&НаКлиенте
Процедура ОтследитьФокус() Экспорт

	Если ТекущийЭлемент <> ПредыдущийЭлемент Тогда
		// фокус сменился: ПредыдущийЭлемент -> ТекущийЭлемент
		ПредыдущийЭлемент = ТекущийЭлемент;
	КонецЕсли;

КонецПроцедуры

⚠️ Это нагрузка на клиент, а в веб-клиенте — лишняя работа браузера. Используйте приём, только если без него задача не решается, и отключайте обработчик через ОтключитьОбработчикОжидания при закрытии формы.

Не дать уйти из поля и вернуть фокус после ошибки

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

Вернуть фокус обработчиком ожидания

Если поставить ТекущийЭлемент прямо в ПриИзменении, фокус часто всё равно уезжает. Платформа завершает переход, который начал пользователь клавишей Tab или кликом, уже после вашего обработчика. Выход — короткая отложенная установка:

&НаКлиенте
Процедура ИННПриИзменении(Элемент)

	Если СтрДлина(Объект.ИНН) <> 10 И СтрДлина(Объект.ИНН) <> 12 Тогда
		ПоказатьПредупреждение(, "ИНН должен содержать 10 или 12 цифр");
		ПодключитьОбработчикОжидания("ВернутьФокусВИНН", 0.1, Истина);
	КонецЕсли;

КонецПроцедуры

&НаКлиенте
Процедура ВернутьФокусВИНН() Экспорт
	ТекущийЭлемент = Элементы.ИНН;
КонецПроцедуры

Третий параметр Истина означает однократный вызов. Без него обработчик будет вызываться каждые 0,1 секунды и «запрёт» пользователя в поле.

Отказ при окончании редактирования строки

У таблицы формы параметр Отказ есть — в событии ПередОкончаниемРедактирования. Если установить его в Истина, строка останется в режиме редактирования, а курсор не уйдёт из неё.

&НаКлиенте
Процедура ТоварыПередОкончаниемРедактирования(Элемент, НоваяСтрока, ОтменаРедактирования, Отказ)

	Если ОтменаРедактирования Тогда
		Возврат; // пользователь нажал Esc — не мешаем
	КонецЕсли;

	Если Элемент.ТекущиеДанные.Количество <= 0 Тогда
		Отказ = Истина;
		Элементы.Товары.ТекущийЭлемент = Элементы.ТоварыКоличество;
	КонецЕсли;

КонецПроцедуры

Проверка ОтменаРедактирования обязательна. Без неё пользователь не сможет выйти из строки даже клавишей Esc.

Сообщение, привязанное к полю

Для ошибок при записи удобнее не держать фокус силой, а показать сообщение с привязкой к полю. Пользователь щёлкает по сообщению — платформа сама активизирует нужный элемент.

Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Не указан договор";
Сообщение.Поле = "Объект.Договор";
Сообщение.Сообщить();

В конфигурациях на БСП то же самое делает ОбщегоНазначенияКлиентСервер.СообщитьПользователю с путём к реквизиту третьим параметром.

Активизация строк и колонок в таблице формы

С таблицами одного ТекущийЭлемент мало. Фокус задаётся на трёх уровнях: сама таблица, строка и колонка.

Что нужноСвойство или метод
Фокус на таблицуТекущийЭлемент = Элементы.Товары
Нужная строкаЭлементы.Товары.ТекущаяСтрока = <идентификатор или ключ>
Нужная колонкаЭлементы.Товары.ТекущийЭлемент = Элементы.ТоварыЦена
Сразу начать редактированиеЭлементы.Товары.ИзменитьСтроку()
Добавить строку и встать в неёЭлементы.Товары.ДобавитьСтроку()

Табличная часть и таблица значений на форме

Для коллекций данных формы в ТекущаяСтрока передают не саму строку, а её идентификатор. Пример: найти первую строку с нулевой ценой и поставить курсор в колонку цены.

&НаКлиенте
Процедура НайтиСтрокуБезЦены(Команда)

	Для Каждого Строка Из Объект.Товары Цикл
		Если Строка.Цена = 0 Тогда
			Элементы.Товары.ТекущаяСтрока = Строка.ПолучитьИдентификатор();
			Элементы.Товары.ТекущийЭлемент = Элементы.ТоварыЦена;
			ТекущийЭлемент = Элементы.Товары;
			Элементы.Товары.ИзменитьСтроку();
			Возврат;
		КонецЕсли;
	КонецЦикла;

	ПоказатьПредупреждение(, "Все цены заполнены");

КонецПроцедуры

Порядок важен: сначала строка и колонка, потом фокус на таблицу, в конце — режим редактирования.

Динамический список

В списке справочника или документа ТекущаяСтрока — это ссылка на объект. Строка должна попадать под текущий отбор, иначе курсор не встанет.

Элементы.Список.ТекущаяСтрока = НайденнаяСсылка;

💡 При вызове формы выбора нужную строку задают через параметр ТекущаяСтрока в параметрах ОткрытьФорму. Это стандартный параметр форм списка и выбора.

Тормоза в ПриАктивизацииСтроки

Если в ПриАктивизацииСтроки есть серверный вызов, при пролистывании списка стрелками клиент начинает «залипать». Практичный приём — отложить обработку:

&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
	ОтключитьОбработчикОжидания("ОбновитьПанельДанных");
	ПодключитьОбработчикОжидания("ОбновитьПанельДанных", 0.2, Истина);
КонецПроцедуры

Пока пользователь листает, обработчик всё время откладывается. Сервер вызывается один раз — когда курсор остановился.

Элементы на страницах и в скрытых группах

Фокус нельзя поставить на элемент, который не виден. Платформа не выдаёт ошибку — курсор просто остаётся на месте. Проверьте всю цепочку родителей элемента.

  • 📄 Страница не активна. Сначала переключите страницу, потом ставьте фокус:
Элементы.ГруппаСтраницы.ТекущаяСтраница = Элементы.СтраницаТовары;
ТекущийЭлемент = Элементы.Товары;
  • 🙈 Видимость = Ложь у самого элемента или у любой группы выше.
  • 🚫 Доступность = Ложь — недоступное поле фокус не получает. Поле с ТолькоПросмотр = Истина получает: в нём можно выделить и скопировать текст.
  • 📁 Свёрнутая группа. У свёртываемой группы есть методы Показать() и Скрыть(). Разверните группу, затем активизируйте поле.
  • ⚙️ Функциональные опции и права. Если элемент скрыт из-за отключённой опции или нехватки прав, в коде лучше заранее проверить его видимость и выбрать запасной вариант.

Фокус после диалогов и в подчинённых окнах

В 8.3 с отключённым режимом модальности код после ПоказатьВопрос или ОткрытьФорму не ждёт закрытия окна. Если поставить ТекущийЭлемент сразу после вызова, это произойдёт до ответа пользователя — и диалог потом вернёт фокус на прежнее место.

Правильно — ставить фокус в обработчике оповещения:

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

&НаКлиенте
Процедура ОчиститьТоварыЗавершение(Ответ, ДополнительныеПараметры) Экспорт

	Если Ответ = КодВозвратаДиалога.Да Тогда
		Объект.Товары.Очистить();
		ТекущийЭлемент = Элементы.Контрагент;
	КонецЕсли;

КонецПроцедуры

Своя форма-диалог

  • 🔸 В открываемой форме фокус задаётся её собственным ТекущийЭлемент в ПриСозданииНаСервере или ПриОткрытии.
  • 🔸 После закрытия окна с режимом БлокироватьОкноВладельца фокус возвращается в форму-владельца, на тот элемент, где он был. Нужен другой — задайте его в обработчике оповещения о закрытии.
  • 🔸 Окно открыто, но спряталось за другими — вызовите у формы Активизировать(). Это и есть тот метод, который путают с установкой фокуса на поле.

Обычные формы (толстый клиент)

В обычных формах принцип тот же, отличается только коллекция элементов:

ФормаКак задать фокус
УправляемаяТекущийЭлемент = Элементы.Контрагент;
ОбычнаяТекущийЭлемент = ЭлементыФормы.Контрагент;

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

Почему фокус не встаёт: разбор ошибок

Диагностика: выберите симптом

Частые вопросы

Можно ли поставить фокус на кнопку командной панели?
Да, кнопка — тоже элемент формы. ТекущийЭлемент = Элементы.ФормаЗаписатьИЗакрыть; переводит на неё фокус, и Enter нажмёт её. Имя кнопки смотрите в дереве элементов.
Работает ли ТекущийЭлемент в веб-клиенте и мобильном клиенте?
Да, свойство поддерживается в тонком, веб- и мобильном клиенте. На мобильном устройстве установка фокуса на поле ввода может сразу открыть экранную клавиатуру — учитывайте это при открытии формы.
Как выделить весь текст в поле после установки фокуса?
Для текстового поля используйте метод поля УстановитьГраницыВыделения() с позициями начала и конца. Вызывайте его после установки ТекущийЭлемент, на клиенте.
Можно ли задать фокус в расширении конфигурации, не меняя типовую форму?
Да. В расширении заимствуйте форму, добавьте обработчик ПриОткрытии с вызовом после типового и присвойте ТекущийЭлемент. Типовой код при этом не меняется, обновления конфигурации проходят проще.