Как изменить доступность поля в управляемой форме в зависимости от значения другого реквизита?

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

Введение в задачу

В практике разработки на платформе 1С:Предприятие часто возникает задача сделать интерфейс отзывчивым и логичным. Классический пример, который мы разберем сегодня: необходимо запретить редактирование поля (например, «Возраст») до тех пор, пока пользователь не заполнит ключевое поле-владелец (например, «Пол»).

Казалось бы, задача тривиальная, но она имеет несколько вариантов решения, каждый из которых подходит для определенных ситуаций. Кроме того, важно различать свойства Доступность и ТолькоПросмотр, так как они по-разному влияют на пользовательский опыт (UX), для улучшения которого иногда применяют даже такие решения, как вертикальные закладки через SVG-картинки.

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

Вариант 1: Условное оформление (Рекомендуемый способ)

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

Разберем по шагам, как это настроить:

  1. Откройте форму справочника или документа в Конфигураторе.
  2. Перейдите на вкладку Условное оформление (обычно она находится внизу окна редактора формы, рядом с вкладками «Элементы», «Реквизиты», «Команды»).
  3. Нажмите кнопку «Добавить» для создания нового элемента оформления.
  4. Настройка оформления: В появившемся окне найдите свойство ТолькоПросмотр (или Доступность). Установите галочку и выберите значение Истина. Это означает: "Сделать поле недоступным, если условие выполнится".
  5. Условие: Перейдите к настройке условия. Нам нужно проверить, что поле «Пол» не заполнено.
    • Левое значение: Выберите поле Объект.Пол.
    • Вид сравнения: Выберите Не заполнено.
  6. Оформляемые поля: Укажите поле, на которое должно влиять это правило — выберите элемент формы Возраст.

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

Вариант 2: Программное управление (Классический способ)

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

Для корректной работы нам нужно, чтобы код срабатывал в двух случаях:

  1. При открытии формы (чтобы установить состояние для уже сохраненных объектов).
  2. В момент изменения пользователем влияющего реквизита.

Шаг 1. Обработка изменения значения

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


&НаКлиенте
Процедура ПолПриИзменении(Элемент)
    
    // Устанавливаем доступность поля Возраст
    // Если Пол заполнен, то ЗначениеЗаполнено вернет Истина -> Доступность = Истина
    Элементы.Возраст.Доступность = ЗначениеЗаполнено(Объект.Пол);
    
    // Дополнительная логика: если пол очистили, имеет смысл очистить и возраст
    Если Не Элементы.Возраст.Доступность Тогда
        Объект.Возраст = 0; 
    КонецЕсли;

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

Шаг 2. Инициализация при открытии

Многие новички совершают ошибку, помещая код проверки в процедуру ПриОткрытии. Хотя это будет работать, более "чистым" подходом для установки начального состояния формы считается использование серверных событий создания формы.

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


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

Если вам нужно проверить поведение элементов прямо во время работы системы, можно использовать специальный редактор форм в режиме предприятия, который позволяет менять свойства элементов "на лету".

Разница между свойствами «Доступность» и «ТолькоПросмотр»

В коде выше мы использовали свойство Доступность (Enabled). Однако давайте разберемся, почему профессионалы часто предпочитают ТолькоПросмотр (ReadOnly).

Код при использовании ТолькоПросмотр немного изменится, так как логика становится обратной:


// Если пол НЕ заполнен, то ТолькоПросмотр = Истина
Элементы.Возраст.ТолькоПросмотр = Не ЗначениеЗаполнено(Объект.Пол);

Архитектурное замечание: Возраст vs Дата Рождения

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

Правильный подход:

  1. Хранить в базе данных реквизит ДатаРождения.
  2. Поле Возраст на форму добавлять как информационную надпись. Аналогичным образом можно реализовать и другие элементы управления, например, флажок в динамическом списке.

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


&НаСервереБезКонтекста
Функция РассчитатьВозраст(ДатаРождения, ДатаАктуальности = Неопределено)
    
    Если Не ЗначениеЗаполнено(ДатаРождения) Тогда
        Возврат 0;
    КонецЕсли;
    
    Если ДатаАктуальности = Неопределено Тогда
        ДатаАктуальности = ТекущаяДата();
    КонецЕсли;

    Возраст = Год(ДатаАктуальности) - Год(ДатаРождения);
    
    Если НачалоДня(ДобавитьМесяц(ДатаРождения, Возраст * 12)) > НачалоДня(ДатаАктуальности) Тогда
        Возраст = Возраст - 1;
    КонецЕсли;
    
    Возврат Возраст;

КонецФункции

Используя этот подход, вам вообще не придется блокировать поле возраста, так как оно станет вычисляемым и недоступным для прямого редактирования по определению.

← На главную