В процессе разработки в среде 1С:Предприятие 8.3 часто возникает задача динамического изменения интерфейса. Типичный сценарий: в зависимости от того, какое значение выбрал пользователь в одном поле (например, «Вид ремонта» или «Тип контрагента»), на форме должны появляться или исчезать другие поля. Это делает форму менее перегруженной и интуитивно понятной для конечного пользователя.
Разберем детально, как реализовать этот механизм, какие ошибки часто допускают начинающие разработчики и как сделать код профессиональным и производительным.
Проанализируем типичную ошибку. Начинающие программисты часто пытаются сравнить значение реквизита со строкой или напрямую обратиться к коллекции перечислений в клиентской процедуре:
&НаКлиенте
Процедура Вид_ремонтаПриИзменении(Элемент)
// Ошибка 1: Сравнение со строкой. Перечисление — это ссылка, а не текст.
Если Объект.Вид_ремонта = "Слесарный ремонт" Тогда
...
КонецЕсли;
// Ошибка 2: Прямое обращение к метаданным. Перечисления недоступны на тонком клиенте.
Если Объект.Вид_ремонта = Перечисления.ВидРемонта.Слесарный Тогда
...
КонецЕсли;
КонецПроцедуры
Выясним причину ошибки: в управляемом приложении 1С разделяет контекст на клиентский и серверный. Глобальный контекст Перечисления доступен только на сервере. Для решения этой задачи на стороне клиента платформа предоставляет специальную функцию ПредопределенноеЗначение().
Рассмотрим правильный синтаксис обращения к элементам перечисления или предопределенным элементам справочников на клиенте. Функция принимает в качестве аргумента строковое имя объекта метаданных.
&НаКлиенте
Процедура Вид_ремонтаПриИзменении(Элемент)
// Получаем значение для сравнения без обращения к серверу
СлесарныйРемонт = ПредопределенноеЗначение("Перечисление.Вид_ремонта.СлесарныйРемонт");
Если Объект.Вид_ремонта = СлесарныйРемонт Тогда
Элементы.Деталь_услуга.Видимость = Истина;
Элементы.КоличествоЧасов.Видимость = Ложь;
Иначе
Элементы.Деталь_услуга.Видимость = Ложь;
Элементы.КоличествоЧасов.Видимость = Истина;
КонецЕсли;
КонецПроцедуры
Важно помнить, что внутри кавычек в функции ПредопределенноеЗначение указывается имя объекта именно так, как оно задано в Конфигураторе (имя, а не синоним).
Если мы напишем код только в событии ПриИзменении, то при открытии уже созданного и записанного документа видимость полей может быть установлена неправильно (по умолчанию будут видны все поля или, наоборот, скрыты нужные). Чтобы избежать дублирования кода, создадим отдельную процедуру.
Проанализируем шаги реализации:
УстановитьВидимостьНаФорме() на клиенте.ПриИзменении реквизита.
&НаКлиенте
Процедура УстановитьВидимостьНаФорме()
// Определяем условия
ЭтоСлесарный = (Объект.Вид_ремонта = ПредопределенноеЗначение("Перечисление.Вид_ремонта.Слесарный"));
ЭтоДиагностика = (Объект.Вид_ремонта = ПредопределенноеЗначение("Перечисление.Вид_ремонта.Диагностика"));
// Управляем элементами
Элементы.ГруппаСлесарныеДанные.Видимость = ЭтоСлесарный;
Элементы.ПолеРезультатДиагностики.Видимость = ЭтоДиагностика;
КонецПроцедуры
&НаКлиенте
Процедура Вид_ремонтаПриИзменении(Элемент)
УстановитьВидимостьНаФорме();
КонецПроцедуры
&НаКлиенте
Процедура ПриОткрытии(Отказ)
УстановитьВидимостьНаФорме();
КонецПроцедуры
Если вам нужно скрыть не один реквизит, а сразу десяток, не стоит прописывать Видимость = Ложь для каждого элемента по отдельности. Посмотрим на более эффективный метод — группировку.
В редакторе формы объедините связанные реквизиты в одну Группу формы (обычную группу без отображения заголовка или группу — страницы). В коде достаточно будет обратиться к имени этой группы:
// Вместо управления 5 полями управляем одной группой
Элементы.ГруппаТехническиеДанныеАвтомобиля.Видимость = (Объект.ТипОбъектаРемонта = ПредопределенноеЗначение("Перечисление.Типы.Автомобиль"));
Это не только упрощает код, но и ускоряет отрисовку интерфейса, так как платформа пересчитывает макет формы один раз для всей группы.
Разберем важный нюанс использования свойств элементов Видимость и Доступность:
Ложь, элемент полностью исчезает с экрана. Соседние элементы могут сдвинуться, чтобы занять освободившееся место.Для управления видимостью на уровне интерфейса (когда поля совсем не нужны) рекомендуется использовать именно Видимость. Доступность чаще используется для логических запретов (например, нельзя редактировать цену, пока не выбрана валюта).
Существует еще один способ управления внешним видом формы, который не требует написания кода в процедурах ПриИзменении — это Условное оформление формы.
Рассмотрим, как это настроить в конфигураторе:
Объект.Вид_ремонта РАВНО "Слесарный").Для управления видимостью основных реквизитов шапки документа программный метод через &НаКлиенте и Элементы...Видимость остается приоритетным и самым гибким.
Если ваше поле «Вид ремонта» — это не перечисление, а справочник, то сравнение через ПредопределенноеЗначение сработает только в том случае, если в справочнике созданы предопределенные элементы (те, что создаются в конфигураторе и помечены «желтой точкой» в режиме 1С:Предприятие).
Если же справочник заполняется пользователями в процессе работы, вам придется сравнивать значения по другим признакам (например, по реквизиту «Категория» или через серверный вызов):
&НаСервере
Функция ЭтоРемонтПерсонала(ЗначениеВидаРемонта)
Возврат ЗначениеВидаРемонта.ТипОбъекта = Перечисления.ТипыОбъектов.Персонал;
КонецФункции
&НаКлиенте
Процедура Вид_ремонтаПриИзменении(Элемент)
// Вызов сервера для получения сложной логики
Если ЭтоРемонтПерсонала(Объект.Вид_ремонта) Тогда
Элементы.ПолеСотрудник.Видимость = Истина;
КонецЕсли;
КонецПроцедуры
Помните, что каждый вызов сервера замедляет работу формы. Старайтесь проектировать метаданные так, чтобы проверки можно было выполнять на клиенте, используя Перечисления или Булевы флаги.