Как реализовать выбор типа и значения в реквизите составного типа без модальных окон

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

При разработке интерфейсов на управляемых формах 1С часто возникает задача: предоставить пользователю возможность выбора значения для реквизита составного типа (например, ОпределяемыйТип), при этом список доступных значений должен динамически формироваться в зависимости от выбранного типа. Рассмотрим ситуацию, когда стандартная кнопка выбора типа не подходит, так как нам нужно жестко ограничить список доступных типов или наложить сложный фильтр, анализируя данные в Регистре Сведений.

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

Анализ проблемы: почему стандартный подход не работает

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

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

Шаг 1. Перехват начала выбора и предложение типов

В первую очередь нам нужно отключить стандартную обработку выбора и предложить пользователю наш собственный список типов. Рассмотрим пример кода для обработчика события НачалоВыбора. Обратите внимание на использование параметра СтандартнаяОбработка.


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

Шаг 2. Обработка выбора типа и получение данных с сервера

Теперь разберем, что происходит после того, как пользователь нажал на нужный тип в списке. Срабатывает процедура ПослеВыбораТипа. На этом этапе нам нужно вызвать серверную функцию, которая проанализирует Регистр Сведений и вернет список доступных подразделений или складов.


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

Шаг 3. Завершение выбора и запись значения

На финальном этапе нам остается только записать выбранный объект в реквизит формы. Посмотрим на пример завершающей процедуры:


&НаКлиенте
Процедура ПослеВыбораЗначения(ВыбранныйЭлемент, ПараметрОповещения) Экспорт
    
    Если ВыбранныйЭлемент <> Неопределено Тогда
        // Присваиваем выбранное значение в реквизит, связанный с полем ввода
        Объект.Подразделение = ВыбранныйЭлемент.Значение;
        
        // Если требуется, вызываем оповещение об изменении для обновления формы
        ЭтаФорма.Модифицированность = Истина;
    КонецЕсли;
    
КонецПроцедуры

Важные нюансы реализации

При использовании данного подхода следует учитывать несколько критически важных моментов:

  1. Параметр ДанныеВыбора: В событии НачалоВыбора параметр ДанныеВыбора предназначен для заполнения выпадающего списка под полем ввода в синхронном режиме. Если мы используем асинхронные вызовы ПоказатьВыборИзСписка, этот параметр игнорируется, так как управление возвращается в платформу до завершения выбора.
  2. Контекст оповещения: В методе ОписаниеОповещения третьим параметром мы передаем Элемент. Это позволяет нам в процедурах обратного вызова точно знать, из какого именно поля на форме был инициирован выбор, что полезно, если на форме несколько похожих реквизитов.
  3. Ограничение типа: Если составной тип определен как ОпределяемыйТип, платформа может не показывать кнопку выбора типа (кнопку "Т"). В этом случае программный вызов списка выбора через СписокЗначений — это единственный способ предоставить пользователю выбор между разными категориями объектов.
  4. Производительность: Старайтесь минимизировать количество серверных вызовов. В процедуре ПослеВыбораТипа серверный вызов неизбежен, так как нам нужно получить данные из базы, но сам список типов в первой процедуре лучше формировать на клиенте.

Альтернативный вариант: Использование свойства ОграничениеТипа

Проанализируем ситуацию: если нам не нужно строить сложный список выбора, а достаточно просто отфильтровать стандартное окно выбора, мы можем использовать ОписаниеТипов. Если в процедуре ПриСозданииНаСервере ограничить доступные типы для реквизита, то стандартная кнопка выбора будет предлагать только их.


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Ограничиваем реквизит только двумя типами программно
    МассивТипов = Новый Массив;
    МассивТипов.Добавить(Тип("СправочникСсылка.Склады"));
    МассивТипов.Добавить(Тип("СправочникСсылка.СтруктурныеЕдиницы"));
    
    НовоеОграничение = Новый ОписаниеТипов(МассивТипов);
    Элементы.Подразделение.ОграничениеТипа = НовоеОграничение;
    
КонецПроцедуры

Однако этот способ не позволит вам динамически формировать СписокЗначений на основе Регистра Сведений так же гибко, как метод с цепочкой оповещений. Рассмотрим его только в тех случаях, когда достаточно стандартного отбора в списках справочников.

Таким образом, мы разобрали наиболее надежный способ реализации сложного выбора для составных типов данных. Использование ОписаниеОповещения и ПоказатьВыборИзСписка позволяет создавать интуитивно понятные интерфейсы, полностью соответствующие стандартам разработки 1С 8.3.

← На главную