Как немодально выбрать значение из списка в 1С:Предприятие 8.3 и избежать ошибок?

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

С развитием платформы 1С:Предприятие 8.3 разработчики столкнулись с необходимостью отказа от модальных окон. Это связано с требованиями работы в веб-клиенте и мобильных приложениях, где блокировка интерфейса браузером или операционной системой недопустима — для управления поведением интерфейса подойдёт управление логикой форм и контролем ввода. Одной из самых частых задач является выбор значения из СписокЗначений. Рассмотрим подробно, как перевести старый модальный код на современные немодальные рельсы, разберем типичные ошибки и новые возможности платформы.

Почему старый код перестал работать?

В старых версиях 1С мы использовали метод ВыбратьЭлемент(), который останавливал выполнение кода до тех пор, пока пользователь не сделает выбор. В современных конфигурациях (например, УТ 11, ERP 2, БП 3) в свойствах конфигурации установлен режим использования модальности Не использовать. При попытке вызвать модальное окно программа выдает ошибку: «Использование модальных окон в данном режиме запрещено».

Способ 1. Использование метода ПоказатьВыборИзСписка

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

Сначала мы создаем процедуру, которая инициирует выбор:


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

Затем создаем процедуру-обработчик. Важно: она обязательно должна иметь ключевое слово Экспорт.


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

Способ 2. Метод объекта СписокЗначений

Проанализируем альтернативный вариант. Начиная с определенных релизов платформы 8.3, у самого объекта СписокЗначений появился метод ПоказатьВыборЭлемента. Он работает аналогично глобальному методу, но иногда более удобен в чтении кода с помощью ИИ-помощника.


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

&НаКлиенте
Процедура ОбработатьВыбор(Элемент, Параметры) Экспорт
    Если Элемент <> Неопределено Тогда
        Сообщить("Вы нажали: " + Элемент.Представление);
    КонецЕсли;
КонецПроцедуры

Способ 3. Асинхронные методы (для платформы 8.3.18 и выше)

Рассмотрим самый современный и удобный способ. Если ваша платформа и режим совместимости позволяют использовать ключевые слова Асинх и Ждать, код снова становится линейным как при асинхронном чтении файла, как в старые добрые времена, но при этом остается немодальным.

Для этого метода не нужно создавать отдельную процедуру-обработчик:


&НаКлиенте
Асинх Процедура ВыполнитьВыборАсинхронно(Команда)
    Список = Новый СписокЗначений;
    Список.Добавить("Опция1");
    Список.Добавить("Опция2");
    
    // Программа приостановит выполнение этой процедуры, но интерфейс не заблокирует
    ВыбранныйЭлемент = Ждать Список.ВыбратьЭлементАсинх("Выберите опцию");
    
    Если ВыбранныйЭлемент <> Неопределено Тогда
        Сообщить("Выбрано: " + ВыбранныйЭлемент.Значение);
    КонецЕсли;
КонецПроцедуры

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

Типичные ошибки и способы их решения

Проанализируем ситуацию, когда программа «вылетает» или выдает ошибку при использовании немодальных вызовов. Рассмотрим основные причины:

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

Использование рефакторинга в Конфигураторе

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

Вариант с подменой СтандартнойОбработки

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


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

Этот способ является наиболее «чистым» с точки зрения архитектуры платформы, так как использует штатный механизм подбора значений в поля формы без написания лишних обработчиков оповещений.

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

← На главную