Как в управляемых формах 1С открыть форму выбора с отбором и получить выбранное значение без модальности?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При переходе на управляемый интерфейс в платформе «1С:Предприятие 8.3» разработчики столкнулись с жестким ограничением: использование модальных окон (включая метод ОткрытьФормуМодально) крайне не рекомендуется, а во многих конфигурациях и вовсе заблокировано на уровне свойств конфигурации («Режим использования модальности» установлен в «Не использовать»). В связи с этим стандартная задача — открыть форму выбора справочника по кнопке, установить в ней фильтр по владельцу и вернуть выбранный элемент — теперь требует совершенно иного, асинхронного подхода.

В этой статье мы подробно разберем, как правильно реализовать этот механизм, детально изучим различные способы решения (как программные, так и без написания кода), а также рассмотрим частые подводные камни, такие как «залипание» отборов при повторном открытии окон и конфликты пользовательских настроек.

Способ 1. Настройка связи параметров выбора в свойствах реквизита (Без написания кода)

Прежде чем приступать к написанию программного кода, проанализируем структуру наших данных. Если задача заключается в том, чтобы при заполнении реквизита на форме (например, «Контактное лицо») происходил автоматический отбор по другому реквизиту (например, «Контрагент» или «Партнер»), платформа предоставляет мощный встроенный механизм декларативной связи.

Выясним, как настроить этот механизм в конфигураторе без единой строчки кода:

  1. Откроем нужную управляемую форму в конфигураторе и выберем реквизит, для которого необходимо настроить отбор при выборе (например, КонтактноеЛицо).
  2. В палитре свойств этого реквизита найдем свойство Связи параметров выбора.
  3. Нажмем на кнопку выбора (три точки) и добавим новую связь.
  4. В колонке «Имя параметра выбора» укажем предопределенный параметр отбора, например, Отбор.Владелец (или Отбор.Партнер в зависимости от структуры подчинения ваших справочников).
  5. В колонке «Путь к данным» выберем реквизит нашей формы, который должен выступать в роли фильтра, например, Объект.Партнер.

После этой простой настройки платформа автоматически возьмет на себя всю работу. При нажатии кнопки выбора в поле «Контактное лицо» система откроет форму выбора справочника, сама установит жесткий отбор по значению, указанному в поле «Партнер», и вернет выбранный элемент обратно в поле ввода.

Способ 2. Программное открытие формы с использованием ОписанияОповещения

Бывают ситуации, когда выбор значения привязан не к стандартному полю ввода, а к произвольной кнопке на форме, при нажатии на которую необходимо выполнить сложную логику, открыть форму выбора и затем обработать полученный результат на клиенте. В управляемых формах для этих целей применяется асинхронный метод ОткрытьФорму совместно с объектом ОписаниеОповещения.

Разберем этот процесс по шагам. Создадим программный алгоритм вызова формы выбора контактных лиц с фильтром по текущему партнеру:


&НаКлиенте
Процедура ОткрытьВыборКонтактногоЛица(Команда)
    
    // 1. Формируем структуру параметров для открываемой формы
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("РежимВыбора", Истина);
    ПараметрыФормы.Вставить("ЗакрыватьПриВыборе", Истина);
    
    // 2. Добавляем структуру отбора. Ключ "Партнер" должен соответствовать имени реквизита в целевом справочнике
    Отбор = Новый Структура;
    Отбор.Вставить("Партнер", Объект.Партнер);
    ПараметрыФормы.Vставить("Отбор", Отбор);
    
    // 3. Создаем ОписаниеОповещения, указывая имя экспортной процедуры обратного вызова
    ОбработкаВыбора = Новый ОписаниеОповещения("ПослеВыбораКонтактногоЛица", ЭтотОбъект);
    
    // 4. Открываем форму выбора программно
    ОткрытьФорму("Справочник.КонтактныеЛицаПартнеров.ФормаВыбора", 
                 ПараметрыФормы, 
                 ЭтаФорма, 
                 Новый УникальныйИдентификатор, // Ключ уникальности (предотвращает зависание отборов)
                 , 
                 , 
                 ОбработкаВыбора, 
                 РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);

КонецПроцедуры

Теперь нам необходимо обязательно описать процедуру-получатель, в которую платформа передаст выбранное пользователем значение. Обратите внимание на важные требования к этой процедуре: она должна располагаться на клиенте (директива &НаКлиенте), иметь ключевое слово Экспорт и строго определенные входящие параметры:


&НаКлиенте
Процедура ПослеВыбораКонтактногоЛица(РезультатВыбора, ДополнительныеПараметры) Экспорт
    
    // Проверяем, выбрал ли пользователь значение или просто закрыл окно
    Если РезультатВыбора <> Неопределено Тогда
        // Обрабатываем полученную ссылку
        Объект.КонтактноеЛицо = РезультатВыбора;
        ПоказатьОповещениеПользователя("Успешно", , "Выбрано контактное лицо: " + РезультатВыбора);
    КонецЕсли;
    
КонецПроцедуры

Как решить проблему «залипания» и сохранения старых отборов?

Разберем типичную ошибку начинающих разработчиков. Часто при повторном открытии формы выбора для совершенно другого контрагента внутри списка отображаются данные старого контрагента. Выясним причину этого поведения.

Дело в том, что по умолчанию платформа оптимизирует ресурсы и кэширует открытые окна. Если при вызове функции ОткрытьФорму четвертый параметр (КлючУникальности) оставлен пустым, система пытается повторно использовать уже созданную ранее форму для текущего владельца. В этот момент новые параметры отбора попросту игнорируются.

Чтобы гарантировать открытие абсолютно новой формы с актуальными параметрами, всегда передавайте в качестве ключа уникальности новый GUID. Сделать это можно с помощью конструкции Новый УникальныйИдентификатор прямо в вызове метода:


ОткрытьФорму("Справочник.КонтактныеЛицаПартнеров.ФормаВыбора", 
             ПараметрыФормы, 
             ЭтаФорма, 
             Новый УникальныйИдентификатор, // Генерация уникального ключа для каждого открытия
             , , 
             ОбработкаВыбора);

Использование ФиксированныхНастроек для обхода конфликтов и сложных условий

Передача условий фильтрации через параметр Отбор имеет два существенных недостатка:

  1. Если пользователь ранее устанавливал в этой форме выбора ручные настройки, платформа при попытке сопоставить их с вашими программными отборами может выдать ошибку: «Невозможно применить фиксированные настройки. Пересекаются элементы отбора». Это связано с активным свойством динамического списка «Автоматическое сохранение пользовательских настроек».
  2. Передача через структуру поддерживает только тип сравнения «Равно». Вы не сможете отфильтровать список по условию «Не равно», «В списке» или сделать отбор по датам.

Для обхода этих ограничений рекомендуется использовать передачу отборов через объект НастройкиКомпоновкиДанных в параметре ФиксированныеНастройки. Рассмотрим пример реализации такого подхода:


&НаКлиенте
Процедура ОткрытьВыборСФиксированнымиНастройками(Команда)

    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("РежимВыбора", Истина);
    
    // Создаем настройки компоновки данных
    НастройкиКомпоновки = Новый НастройкиКомпоновкиДанных;
    
    // Добавляем элемент отбора
    ЭлементОтбора = НастройкиКомпоновки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    ЭлементОтбора.ЛевоеЗначение  = Новый ПолеКомпоновкиДанных("Партнер");
    ЭлементОтбора.ВидСравнения   = ВидСравненияКомпоновкиДанных.Равно;
    ЭлементОтбора.ПравоеЗначение = Объект.Партнер;
    ЭлементОтбора.Использование  = Истина;
    
    // Помещаем настройки в параметры открытия формы
    ПараметрыФормы.Вставить("ФиксированныеНастройки", НастройкиКомпоновки);
    
    ОбработкаВыбора = Новый ОписаниеОповещения("ПослеВыбораКонтактногоЛица", ЭтотОбъект);
    
    ОткрытьФорму("Справочник.КонтактныеЛицаПартнеров.ФормаВыбора", 
                 ПараметрыФормы, 
                 ЭтаФорма, 
                 Новый УникальныйИдентификатор, 
                 , , 
                 ОбработкаВыбора);

КонецПроцедуры

Важное преимущество: Отборы, переданные через механизм фиксированных настроек, защищены платформой от изменения пользователем. Конечный пользователь увидит отфильтрованный список и не сможет случайно отключить или отредактировать переданный вами программный фильтр в процессе подбора элементов.

← На главную