Отключаем кнопку на управляемой форме 1С 8.3: свойства, код, роли и статус документа
Содержание
Чтобы сделать кнопку неактивной в 1С 8.3, снимите у элемента формы флажок Доступность в палитре свойств или выполните в модуле формы строку Элементы.ИмяКнопки.Доступность = Ложь;. Кнопка станет серой и перестанет нажиматься, но останется на месте. Если её нужно спрятать совсем — используйте свойство Видимость.
Сложности начинаются, когда кнопка должна гаснуть не всегда, а по условию: для части пользователей, после проведения документа, при пустой строке в таблице. Ниже пять рабочих способов для управляемых форм, отдельный блок для обычных форм толстого клиента и разбор ошибок, из-за которых кнопка «не слушается».
Подготовка: имя кнопки, команда и свойство Доступность
На управляемой форме кнопка и команда — разные объекты. Команда живёт на вкладке Команды редактора формы и описывает действие. Кнопка — элемент на вкладке Элементы, который на эту команду ссылается.
Отсюда первая ловушка. Если перетащить команду Заполнить в командную панель формы, платформа назовёт кнопку ФормаЗаполнить, а не Заполнить. В коде обращаются именно к имени элемента.
Что проверить перед работой:
- 🔎 Имя элемента. Выделите кнопку в дереве элементов и посмотрите свойство
Имяв палитре. - 🧩 Где лежит кнопка. В командной панели формы, в группе, в командной панели таблицы или прямо на форме — от этого зависит каскадная блокировка.
- ⚙️ Тип формы. Управляемая форма (тонкий клиент, веб-клиент, «Такси») или обычная форма толстого клиента. Код у них разный.
Три свойства, которые часто путают:
| Свойство | Как выглядит кнопка | Когда применять |
|---|---|---|
Доступность = Ложь | Видна, серая, не нажимается | Действие временно невозможно, пользователь должен понимать, что оно есть |
Видимость = Ложь | Не отображается | Пользователю функция не положена вообще |
ТолькоПросмотр = Истина (у формы) | Гаснут команды, изменяющие данные | Нужно запретить редактирование всей формы разом |
Серая кнопка без пояснения раздражает. Заполните у неё Подсказку: «Доступно только для непроведённого документа». Подсказка показывается и у неактивной кнопки.
Отключение кнопки через свойства формы в конфигураторе
Самый простой способ — статический. Кнопка будет неактивна всегда, пока её не включит код.
- Откройте конфигуратор, найдите объект и откройте нужную форму.
- На вкладке
Элементывыделите кнопку. - Откройте палитру свойств (
Alt+Enterили двойной щелчок). - В группе свойств «Использование» снимите флажок
Доступность. - Сохраните конфигурацию и обновите конфигурацию базы данных (
F7).
Так обычно делают кнопку, которая включается только после выполнения условия: например, «Отправить» гаснет при открытии формы, а код включает её после заполнения обязательных полей.
Если кнопки ещё нет в дереве элементов, её сначала добавляют: перетащите команду из вкладки Команды в нужную командную панель. Стандартные кнопки автоматической командной панели («Записать», «Провести») отдельными элементами в дереве не видны. Чтобы управлять ими поштучно, отключите у командной панели автозаполнение или добавьте стандартную команду в панель вручную — тогда появится элемент с именем.
Функциональные опции
Если кнопка должна зависеть от настройки программы, а не от данных формы, используйте функциональные опции. У команды формы есть свойство Функциональные опции: выберите опцию, и при её выключенном значении команда и все кнопки на неё исчезнут без единой строки кода.
Как сделать кнопку неактивной программно в модуле формы
Программное управление нужно, когда доступность зависит от данных. Базовая строка одна:
Элементы.ФормаЗаполнить.Доступность = Ложь;
Свойства элементов формы можно менять и на клиенте, и на сервере. Вызов сервера ради одной кнопки не нужен.
Правильная схема — одна процедура, которая пересчитывает доступность всех зависимых кнопок, и вызовы её из нескольких мест:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
УстановитьДоступностьКнопок();
КонецПроцедуры
&НаКлиенте
Процедура КонтрагентПриИзменении(Элемент)
УстановитьДоступностьКнопок();
КонецПроцедуры
&НаКлиентеНаСервереБезКонтекста
Процедура УстановитьДоступностьКнопокПоДанным(Элементы, Объект)
ЕстьКонтрагент = ЗначениеЗаполнено(Объект.Контрагент);
Элементы.ФормаЗаполнить.Доступность = ЕстьКонтрагент;
Элементы.ФормаОтправить.Доступность = ЕстьКонтрагент И Объект.Товары.Количество() > 0;
КонецПроцедуры
&НаКлиентеНаСервере
Процедура УстановитьДоступностьКнопок()
УстановитьДоступностьКнопокПоДанным(Элементы, Объект);
КонецПроцедуры
Директива &НаКлиентеНаСервере позволяет звать одну и ту же процедуру из серверного обработчика и из клиентского ПриИзменении. Логика не дублируется, и кнопка ведёт себя одинаково при открытии формы и при правке поля.
Неактивная кнопка не защищает данные. Пользователь может выполнить то же действие из другой формы, обработкой или через внешнее соединение. Проверку «можно ли» дублируйте в обработчике команды и в модуле объекта (ПередЗаписью, ОбработкаПроверкиЗаполнения).
Минимальная защита в обработчике команды выглядит так:
&НаКлиенте
Процедура Отправить(Команда)
Если Не ЗначениеЗаполнено(Объект.Контрагент) Тогда
ПоказатьПредупреждение(, "Сначала выберите контрагента.");
Возврат;
КонецЕсли;
ОтправитьНаСервере();
КонецПроцедуры
Условие то же, что и в процедуре пересчёта доступности. Его удобно вынести в отдельную функцию и звать из обоих мест, чтобы правила не разошлись при следующей доработке.
Блокировка кнопок через роли и права доступа
Для ограничения по пользователям есть два пути: декларативный и программный.
Без кода
- 🛡️ Права на команду. Общие команды и команды объектов метаданных имеют в ролях право
Просмотр. Снимите его — кнопка, связанная с командой, у пользователя пропадёт. - 👁️ Видимость по ролям. У элемента формы в палитре свойств рядом с
Видимостьнастраивается видимость для конкретных ролей. Это скрывает кнопку, а не делает её серой. - 📄 Права на объект. Если у роли нет права
Изменениена документ, форма открывается только для просмотра, и команды с флажкомИзменяет сохраняемые данныегаснут сами.
В коде
Когда нужно именно «серая, но видна», проверьте роль или право при создании формы:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
МожноПроводить = ПравоДоступа("Проведение", Метаданные.Документы.ЗаказПоставщику);
Элементы.ФормаПровестиИЗакрыть.Доступность = МожноПроводить;
Элементы.ФормаОтменитьСогласование.Доступность = РольДоступна("ПолныеПрава")
Или РольДоступна("СогласованиеЗаказов");
КонецПроцедуры
ПравоДоступа() надёжнее, чем РольДоступна(). Права могут прийти из нескольких ролей, и проверка по одному имени роли ломается, когда администратор переименует или разделит роли. Проверку по роли оставляйте для особых случаев, когда нужна именно эта роль.
Права не меняются, пока открыта форма. Проверяйте их один раз в ПриСозданииНаСервере и сохраняйте результат в реквизит формы, если он понадобится на клиенте.
Кнопка неактивна в зависимости от статуса документа
Частая задача: после проведения или согласования кнопки «Заполнить» и «Подобрать» должны гаснуть. Статус меняется не только при открытии, поэтому процедуру пересчёта вызывают в трёх местах.
| Событие формы | Зачем вызывать пересчёт |
|---|---|
ПриСозданииНаСервере | Новый документ или копия |
ПриЧтенииНаСервере | Открытие существующего документа и перечитывание |
ПослеЗаписиНаСервере | Документ только что провели или поменяли статус |
Пример для документа со стандартным реквизитом Проведен и своим реквизитом Статус:
&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
УстановитьДоступностьПоСтатусу();
КонецПроцедуры
&НаСервере
Процедура ПослеЗаписиНаСервере(ТекущийОбъект, ПараметрыЗаписи)
УстановитьДоступностьПоСтатусу();
КонецПроцедуры
&НаСервере
Процедура УстановитьДоступностьПоСтатусу()
Черновик = Не Объект.Проведен
И Объект.Статус = Перечисления.СтатусыЗаказов.Черновик;
Элементы.ФормаЗаполнить.Доступность = Черновик;
Элементы.ТоварыПодбор.Доступность = Черновик;
Элементы.ФормаСогласовать.Доступность = Объект.Статус = Перечисления.СтатусыЗаказов.НаСогласовании;
КонецПроцедуры
ПриЧтенииНаСервере не вызывается для нового документа, поэтому для него нужен вызов из ПриСозданииНаСервере с проверкой Объект.Ссылка.Пустая() или безусловно — лишний пересчёт стоит дёшево.
Кнопки табличной части и списка
Кнопки, которые зависят от текущей строки, пересчитывают в обработчике ПриАктивизацииСтроки таблицы. Данные строки берут через Элементы.Список.ТекущиеДанные — на клиенте, без вызова сервера:
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
Строка = Элементы.Список.ТекущиеДанные;
Элементы.СписокОтменитьПроведение.Доступность = Строка <> Неопределено И Строка.Проведен;
КонецПроцедуры
Для динамического списка поле, которое читает код, должно быть в выборке. Если колонки на форме нет, отметьте у поля в списке реквизитов флажок Использовать всегда, иначе в ТекущиеДанные его не будет.
Условное оформление, группы и каскадная блокировка
Почему условное оформление не подходит для кнопок
Условное оформление управляемой формы применяется к полям и колонкам таблиц: цвет, шрифт, Видимость, Доступность, ТолькоПросмотр. На кнопки оно не действует. Если нужно погасить ввод в колонке «Цена» для строк со скидкой — это условное оформление. Если гасить кнопку — это код.
Зато условное оформление снимает нагрузку с ПриАктивизацииСтроки: блокировка полей в строках таблицы работает на стороне платформы и не требует обработчиков вообще.
Каскадная блокировка группой
Если гаснуть должны сразу пять кнопок, не перечисляйте их в коде. Положите их в одну группу кнопок или подменю и меняйте доступность группы:
Элементы.ГруппаДействияСЗаказом.Доступность = Черновик;
Недоступность группы распространяется на все вложенные элементы. Свойства самих кнопок при этом не меняются: когда группа снова станет доступна, каждая кнопка вернётся в своё прежнее состояние. Так удобно строить два уровня: группа отвечает за статус документа, отдельные кнопки — за права.
Блокировка всей формы
ЭтотОбъект.ТолькоПросмотр = Истина; переводит форму в просмотр. Команды, у которых в свойствах отмечено Изменяет сохраняемые данные, становятся неактивными автоматически. Для своих команд, которые пишут в базу, этот флажок стоит ставить всегда — тогда они погаснут вместе со стандартными «Записать» и «Провести».
Неактивная кнопка в обычных формах толстого клиента
В старых конфигурациях на обычных формах (толстый клиент, интерфейс 8.2) элементы доступны через коллекцию ЭлементыФормы. Кнопка в командной панели — это элемент коллекции Кнопки этой панели:
Процедура ПриОткрытии()
ЭлементыФормы.КоманднаяПанель1.Кнопки.Заполнить.Доступность = Не Проведен;
ЭлементыФормы.КнопкаПечать.Доступность = Не ЭтоНовый();
КонецПроцедуры
Отличия от управляемых форм:
- 🖥️ Нет разделения на клиент и сервер, директивы
&НаКлиентене нужны. - 🗂️ Кнопка на форме и кнопка в командной панели адресуются по-разному: напрямую через
ЭлементыФормыили черезКнопкипанели. - 🔁 Пересчёт после записи ставят в
ПослеЗаписи(), а не вПослеЗаписиНаСервере.
Чтобы блокировка не тормозила форму
Сама строка Доступность = Ложь выполняется мгновенно. Тормоза дают вызовы сервера и запросы, которые ради неё делают.
- 🚫 Не ходите на сервер из
ПриАктивизацииСтроки. Событие срабатывает при каждом движении курсора. При листании списка стрелкой это десятки серверных вызовов в секунду. - 📦 Готовьте данные заранее. Права, настройки, статус — один раз при создании формы, в реквизиты формы. На клиенте читайте уже готовые значения.
- ⏱️ Откладывайте пересчёт. Если без сервера не обойтись, подключите обработчик ожидания: он сработает, когда пользователь остановится на строке.
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
ОтключитьОбработчикОжидания("ОбновитьДоступностьКнопок");
ПодключитьОбработчикОжидания("ОбновитьДоступностьКнопок", 0.2, Истина);
КонецПроцедуры
&НаКлиенте
Процедура ОбновитьДоступностьКнопок()
Строка = Элементы.Список.ТекущиеДанные;
Если Строка = Неопределено Тогда
Элементы.СписокСогласовать.Доступность = Ложь;
Возврат;
КонецЕсли;
Элементы.СписокСогласовать.Доступность = МожноСогласовать(Строка.Ссылка);
КонецПроцедуры
&НаСервереБезКонтекста
Функция МожноСогласовать(Ссылка)
Возврат Ссылка.Статус = Перечисления.СтатусыЗаказов.НаСогласовании;
КонецФункции
&НаСервереБезКонтекста не передаёт на сервер данные формы, поэтому вызов лёгкий. Третий параметр Истина у ПодключитьОбработчикОжидания делает обработчик однократным. Ещё лучше — добавить поле Статус в динамический список и не звать сервер совсем.
Почему кнопка не гаснет и другие ошибки
Как сделать неактивной кнопку в типовой конфигурации без снятия с поддержки?
ПриСозданииНаСервере с вызовом «После», где поменяйте Доступность кнопки. Типовой код при этом не трогается.Можно ли сделать неактивной кнопку в шапке списка «Создать»?
Добавление на объект: команда создания погаснет везде. Для одной формы списка добавьте стандартную команду в командную панель вручную и управляйте доступностью элемента.Чем «Доступность» отличается от «ТолькоПросмотр» у поля?
ТолькоПросмотр выглядит обычно, значение можно выделить и скопировать, но не изменить. Поле с Доступность = Ложь серое и вообще не получает фокус. У кнопки свойства ТолькоПросмотр нет.Как сделать кнопку неактивной, пока не заполнены обязательные поля?
ПриИзменении каждого обязательного поля. Окончательную проверку оставьте в ОбработкаПроверкиЗаполнения.Работает ли такой код в веб-клиенте и мобильном клиенте?
Доступность и Видимость элементов управляемой формы одинаково работают в тонком, веб- и мобильном клиенте.