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