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