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