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