Разработка и Конфигурация · 13 мин
Как передать параметры при закрытии формы 1С
Как передать параметры при закрытии формы в 1С: метод Закрыть с параметром, ОповеститьОВыборе, ОписаниеОповещения, обработка результата в форме-владельце.
При разработке управляемых форм в 1С:Предприятие регулярно возникает задача: пользователь открыл дочернюю форму (выбор элемента, настройки, ввод данных), поработал с ней, закрыл — и результат нужно вернуть в форму, которая её открывала. Платформа предоставляет для этого несколько механизмов, и выбор зависит от того, кто открыл форму, нужен ли результат только владельцу или нескольким подписчикам, и работаете ли вы с модальным или немодальным режимом.
Основные способы передачи данных при закрытии: передача значения через параметр метода Закрыть(), вызов ОповеститьОВыборе(), использование произвольных оповещений через Оповестить() и обработка результата через ОписаниеОповещения при открытии формы. Ниже разобраны все варианты с примерами кода и типичными ошибками.
Как работает передача данных при закрытии формы
В управляемом приложении формы не вызываются модально с возвратом значения, как это было в обычном приложении 1С 8.2 с методом ОткрытьМодально(). Вместо этого используется асинхронная модель: форма-владелец открывает дочернюю форму и передаёт ей описание оповещения — указание, какую процедуру вызвать, когда дочерняя форма закроется и вернёт результат.
Результат закрытия доступен в двух точках: в оповещении, переданном в ОткрытьФорму() или ПоказатьВводЗначения(), и в обработчике ОбработкаВыбора() формы-владельца, если дочерняя форма вызвала ОповеститьОВыборе(). Важно понимать: значение, переданное в Закрыть(), попадает только в оповещение открытия, а не в ОбработкаВыбора.
Если форма открыта не из вашей формы (например, открыта независимо из списка), владельца может не быть, и переданный параметр никто не получит. Поэтому перед разработкой определите сценарий: кто открывает форму и кто должен получить результат.
Передача значения через Закрыть(ПараметрЗакрытия)
Метод Закрыть() дочерней формы принимает необязательный параметр — произвольное значение, которое будет передано в описание оповещения, указанное при открытии формы. Это может быть примитивное значение, ссылка, структура или массив.
Пример кода в дочерней форме (команда «Выбрать»):
&НаКлиенте
Процедура Выбрать(Команда)
Результат = Новый Структура;
Результат.Вставить("Контрагент", ВыбранныйКонтрагент);
Результат.Вставить("Договор", ВыбранныйДоговор);
Закрыть(Результат);
КонецПроцедуры
Код в форме-владельце, которая открывает дочернюю форму и получает результат:
&НаКлиенте
Процедура ПодобратьКонтрагента(Команда)
ОписаниеОповещения = Новый ОписаниеОповещения("ПослеВыбораКонтрагента", ЭтотОбъект);
ОткрытьФорму("Справочник.Контрагенты.Форма.ФормаПодбора", , ЭтотОбъект, , , , ОписаниеОповещения);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораКонтрагента(Результат, ДополнительныеПараметры) Экспорт
Если Результат = Неопределено Тогда
Возврат; // пользователь закрыл форму без выбора
КонецЕсли;
Объект.Контрагент = Результат.Контрагент;
Объект.Договор = Результат.Договор;
КонецПроцедуры
Ключевой момент: если пользователь закрыл форму крестиком или клавишей Esc, в оповещение придёт Неопределено. Поэтому проверка результата на Неопределено обязательна, иначе получите ошибку обращения к полю структуры.
Передача результата через ОповеститьОВыборе
Метод ОповеститьОВыборе(Значение) предназначен для форм, открытых в режиме выбора. Он вызывает обработчик ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора) в форме-владельце. Именно так работают стандартные формы выбора справочников: пользователь дважды щёлкает по элементу, форма вызывает ОповеститьОВыборе и закрывается.
&НаКлиенте
Процедура СписокВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
ОповеститьОВыборе(ВыбраннаяСтрока);
КонецПроцедуры
В форме-владельце обработка выглядит так:
&НаКлиенте
Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора)
Если ТипЗнч(ВыбранноеЗначение) = Тип("СправочникСсылка.Номенклатура") Тогда
Объект.Номенклатура = ВыбранноеЗначение;
КонецЕсли;
КонецПроцедуры
Чтобы форма при открытии вела себя как форма выбора, при вызове ОткрытьФорму() передайте параметр РежимОткрытияОкна = БлокироватьОкноВладельца и установите у формы-владельца связь через параметр «Владелец». Для полей ввода с кнопкой выбора платформа сама направит оповещение в нужное поле, если форма открыта стандартным механизмом выбора.
Когда выбрать ОповеститьОВыборе вместо Закрыть с параметром
Используйте ОповеститьОВыборе, если форма является формой выбора по смыслу и может открываться стандартными механизмами платформы (кнопка выбора в поле ввода, подбор). Используйте Закрыть(Результат) с описанием оповещения, когда логика обработки результата специфична для конкретной кнопки или команды и не должна пересекаться со стандартной обработкой выбора.
Передача данных через Оповестить для нескольких получателей
Если результат закрытия формы должны получить несколько форм или форма-владелец неизвестна, используйте метод Оповестить(ИмяСобытия, Параметр, Источник). Все формы, у которых есть обработчик ОбработкаОповещения(ИмяСобытия, Параметр, Источник), получат это сообщение.
&НаКлиенте
Процедура ПрименитьНастройки(Команда)
ПараметрыРезультата = Новый Структура("Период, Склад", Период, Склад);
Оповестить("ИзмененыНастройкиОтчета", ПараметрыРезультата, ЭтотОбъект);
Закрыть();
КонецПроцедуры
В форме-получателе:
&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
Если ИмяСобытия = "ИзмененыНастройкиОтчета" Тогда
ЗаполнитьНастройки(Параметр);
СформироватьОтчет();
КонецЕсли;
КонецПроцедуры
Имя события выбирайте уникальным в рамках конфигурации, чтобы не пересечься со стандартными оповещениями типа «Запись_Контрагента». Хорошая практика — добавлять префикс подсистемы, например "СКЛ_ИзмененыНастройкиОтчета".
Блокирующие и модальные формы
Если дочерняя форма блокирует окно владельца (параметр РежимОткрытияОкна = БлокироватьОкноВладельца), логика передачи результата не меняется: используется тот же Закрыть(Результат) и описание оповещения. Разница только в том, что пользователь не сможет переключиться на форму-владельца, пока не закроет дочернюю.
Полностью модальный режим (ОткрытьМодально()) в управляемом приложении считается устаревшим и в режиме совместимости «Не использовать» недоступен. Вместо него платформа предлагает методы с постфиксом «Асинх» и описания оповещений: ПоказатьВопрос(), ПоказатьВводЗначения(), ПоказатьВводСтроки(). Для простых сценариев (ввести число, строку, выбрать значение из списка) эти методы заменяют отдельную дочернюю форму целиком.
&НаКлиенте
Процедура УказатьКоличество(Команда)
ОписаниеОповещения = Новый ОписаниеОповещения("ПослеВводаКоличества", ЭтотОбъект);
ПоказатьВводЧисла(ОписаниеОповещения, 1, "Введите количество", 15, 3);
КонецПроцедуры
Как выбрать действие
Проверка результата и обработка отказа от выбора
Надёжный код обработки результата всегда учитывает три ситуации: пользователь сделал выбор и подтвердил его, пользователь закрыл форму без выбора, пользователь передал значение, которое не проходит проверку в форме-владельце.
Как проверить результат
В оповещение пришла структура или ссылка с ожидаемыми полями
Пришло Неопределено — значит, Закрыть вызван без параметра
В оповещении получено Неопределено, обработчик завершился без изменений
Ошибка обращения к полю результата — отсутствует проверка на Неопределено
Тип значения проверен через ТипЗнч перед присвоением реквизиту
Значение присваивается без проверки типа — возможны ошибки при нештатном сценарии
Если дочерняя форма редактирует данные, полезно перед закрытием спрашивать подтверждение. Для этого в обработчике ПередЗакрытием установите Отказ = Истина, покажите вопрос и в обработчике ответа вызовите Закрыть(Результат) повторно — уже без отказа.
&НаКлиенте
Процедура ПередЗакрытием(Отказ, ЗавершениеРаботы, ТекстПредупреждения, СтандартнаяОбработка)
Если Модифицированность И Не ЗавершениеРаботы Тогда
Отказ = Истина;
ОписаниеОповещения = Новый ОписаниеОповещения("ПослеВопросаОСохранении", ЭтотОбъект);
ПоказатьВопрос(ОписаниеОповещения, "Сохранить изменения?", РежимДиалогаВопрос.ДаНетОтмена);
КонецЕсли;
КонецПроцедуры
Типичные ошибки при передаче параметров закрытия
Большинство проблем в этом механизме связано не с самим вызовом Закрыть(), а с нарушением контракта между формой-владельцем и дочерней формой: одна ожидает структуру, другая передаёт ссылку, либо оповещение вообще не зарегистрировано.
Отдельно отметим: процедура, указанная в ОписаниеОповещения, должна быть объявлена с директивой &НаКлиенте и словом Экспорт, принимать два параметра — результат и дополнительные параметры. Если оповещение создаётся с указанием модуля, отличного от текущего, процедура должна существовать именно в нём.
- 1Определите, что должна вернуть дочерняя форма, и сформируйте структуру результата
- 2В дочерней форме в команде подтверждения вызовите Закрыть(Результат)
- 3В форме-владельце создайте процедуру обработки с параметрами (Результат, ДополнительныеПараметры) и Экспорт
- 4Откройте форму через ОткрытьФорму с ОписаниеОповещения на эту процедуру
- 5В обработчике проверьте Результат на Неопределено и тип значения
- 6Протестируйте три сценария: подтверждение выбора, закрытие крестиком, закрытие по Esc
FAQ
Можно ли передать параметр закрытия, если форма открыта из другой формы не моего кода?
Нет, параметр метода Закрыть() получает только тот, кто передал описание оповещения при открытии. Если форму открывает чужой или стандартный код, используйте Оповестить() с уникальным именем события — тогда ваш обработчик ОбработкаОповещения получит данные независимо от того, кто открыл форму.
Чем отличается Закрыть(Значение) от ОповеститьОВыборе(Значение)?
Закрыть(Значение) передаёт результат в описание оповещения, указанное при открытии формы. ОповеститьОВыборе(Значение) вызывает обработчик ОбработкаВыбора в форме-владельце и работает со стандартными механизмами выбора, например с кнопкой выбора в поле ввода. Одновременно использовать оба способа в одной форме можно, но обычно это избыточно.
Почему в обработчике оповещения приходит Неопределено, хотя я вызываю Закрыть(Результат)?
Чаще всего форма открыта без описания оповещения, либо оповещение указывает на другую процедуру или другой модуль. Также проверьте, что форма действительно закрывается через Закрыть(Результат), а не через стандартную кнопку закрытия, которая вызывает Закрыть() без параметра.
Можно ли передать из закрываемой формы таблицу значений?
Технически таблицу значений можно поместить во временное хранилище методом ПоместитьВоВременноеХранилище на сервере и передать в результате закрытия адрес хранилища. Передавать саму таблицу напрямую в клиентское оповещение нельзя — используйте адрес во временном хранилище и загрузите данные на сервере формы-получателя.
Как запретить закрытие формы без заполнения обязательных полей?
В обработчике ПередЗакрытием проверьте заполненность полей и установите Отказ = Истина, если данные неполные. Учтите, что при завершении работы сеанса (параметр ЗавершениеРаботы = Истина) блокировать закрытие бессмысленно — в этом случае просто отмените отказ или зафиксируйте несохранённые данные.
Работает ли передача параметра закрытия в веб-клиенте и мобильном клиенте?
Да, механизм описаний оповещений и параметр метода Закрыть работают во всех клиентах управляемого приложения: тонком, толстом, веб-клиенте и мобильном клиенте. Ограничения касаются только устаревшего модального режима, который в веб-клиенте может требовать специальных настроек браузера и потому не рекомендуется.
Что важно запомнить
Возврат значения при закрытии формы делается через Закрыть(Результат) и ОписаниеОповещения при открытии; для форм выбора — через ОповеститьОВыборе. Всегда проверяйте результат на Неопределено, объявляйте обработчик с Экспорт и передавайте компактные структуры вместо объектов формы.