Как реализовать динамическое изменение видимости полей формы в 1С:Предприятии 8.3 на управляемых формах?

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

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

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

Основы управления видимостью элементов формы

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

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

Решение 1: Динамическое изменение видимости на клиенте (простой сценарий)

Наиболее распространенный и простой сценарий – это когда видимость одного поля зависит от значения другого поля, и вся необходимая информация доступна непосредственно на клиенте. Рассмотрим пример, когда у нас есть поле "ТипДокумента", и в зависимости от его значения, нужно показывать или скрывать поле "ПричинаИзменения".

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

Рассмотрим пример кода для данного сценария. Этот код размещается в модуле управляемой формы.


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

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

    // Определяем видимость поля "ПричинаИзменения"
    // Предполагаем, что Перечисления.ТипыДокументов.Приказ существует
    Если ТипДокументаЗначение = Перечисления.ТипыДокументов.Приказ Тогда
        Элементы.ПричинаИзменения.Видимость = Истина;
    Иначе
        Элементы.ПричинаИзменения.Видимость = Ложь;
    КонецЕсли;
КонецПроцедуры

Важные моменты при работе на клиенте:

Инициализация видимости при открытии формы

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


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

Обратите внимание, что мы вызываем клиентскую процедуру ОбновитьВидимостьПолей() из серверного обработчика. Это допустимо, поскольку ПриСозданииНаСервере вызывается первым, а затем управление передается на клиент, где уже можно вызывать клиентские процедуры.

Решение 2: Динамическое изменение видимости с использованием серверных вызовов (сложный сценарий)

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

Рассмотрим сценарий, когда поле "ПричинаИзменения" должно быть видно только для пользователей с определенными правами или если "ТипДокумента" имеет значение "Приказ" И при этом в базе есть некий справочник "ОсобыеПричины", в котором содержится элемент, связанный с текущим пользователем.

  1. Создаем клиентский обработчик: Как и в первом случае, начинаем с клиентского обработчика ПриИзменении для поля "ТипДокумента".
  2. Вызываем серверную функцию: Из этого обработчика мы будем вызывать функцию, помеченную как &НаСервере или &НаСервереБезКонтекста. Эта функция будет выполнять всю сложную логику.
  3. Получаем результат и обновляем видимость: Результат серверной функции возвращается на клиент, где мы уже используем его для изменения свойства Видимость элемента формы.

Разберем подробнее пример кода для этого сценария:


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

&НаСервереБезКонтекста
Функция ПолучитьВидимостьПричиныИзмененияНаСервере(ЗначениеТипаДокумента)
    // Это серверная функция, она не имеет доступа к элементам формы, 
    // но имеет полный доступ к базе данных и серверным методам.
    
    // Пример сложной логики:
    // 1. Проверяем значение ТипаДокумента
    Если ЗначениеТипаДокумента = Перечисления.ТипыДокументов.Приказ Тогда
        // 2. Проверяем дополнительные условия, например, наличие особых прав
        // или специфичные данные в базе
        Перем ТребуетсяПричина;
        ТребуетсяПричина = Истина; // По умолчанию считаем, что требуется

        // Пример: проверка роли или каких-то особых настроек
        // Можно выполнить запрос к базе данных
        // Например, ПроверитьНаличиеЗаписиВСправочнике("НастройкиВидимости", ТекущийПользователь());
        
        Возврат ТребуетсяПричина;
    Иначе
        Возврат Ложь; // Если тип документа не "Приказ", причина не нужна
    КонецЕсли;
КонецФункции

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

    // Вызываем серверную функцию и получаем результат
    ВидимостьПоля = ПолучитьВидимостьПричиныИзмененияНаСервере(ТипДокументаЗначение);
    
    // Обновляем видимость элемента на клиенте
    Элементы.ПричинаИзменения.Видимость = ВидимостьПоля;
КонецПроцедуры

Пояснения к серверному вызову:

Дополнительные рекомендации и частые ошибки

  1. Производительность: Старайтесь минимизировать количество серверных вызовов. Если логику можно полностью реализовать на клиенте, делайте это. Серверные вызовы вносят задержку в работу интерфейса.
  2. Доступность элемента: Убедитесь, что элемент, видимость которого вы меняете, имеет свойство Доступность = Истина, если только вы не хотите одновременно управлять и его доступностью. Если элемент недоступен, изменение видимости может не дать ожидаемого эффекта, или элемент может быть виден, но неактивен.
  3. Группы элементов: Если поле находится внутри группы (например, ГруппаКолонок, Страница), то его видимость также зависит от видимости этой группы и всех ее родительских групп. Если родительская группа скрыта, то и все ее дочерние элементы будут скрыты, независимо от их индивидуальных настроек видимости.
  4. Обработчики событий: Внимательно выбирайте обработчик события. ПриИзменении подходит для полей ввода. Если вам нужно быстро набросать интерфейс для тестов, попробуйте разработку интерфейса по текстовому описанию в стиле Markdown.
  5. Надежность получения значений: При работе с реквизитами формы или объекта всегда проверяйте, что они существуют и имеют ожидаемый тип, особенно если код универсальный.
  6. Отладка: Активно используйте точку останова (Отладчик) и метод Сообщить() для отладки логики видимости. Проверяйте значения переменных и свойств элементов в процессе выполнения.

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

← На главную