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