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