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