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