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