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