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