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