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

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

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

Рассмотрим по шагам, как переписать старый код с использованием ПолучитьФорму() и ОткрытьМодально() на современный немодальный подход с использованием процедуры ОткрытьФорму() и механизма оповещений.

Причина возникновения проблемы

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


// Устаревший модальный код
ФормаВыбора = ПолучитьФорму("Справочник.Контрагенты.ФормаВыбора");
ФормаВыбора.Элементы.Список.Отображение = ОтображениеТаблицы.Список;

ЭлементОтбора = ФормаВыбора.Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Ссылка");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;
ЭлементОтбора.ПравоеЗначение = СписокКонтрагентов;
ЭлементОтбора.Использование = Истина;

Объект.Контрагент = ФормаВыбора.ОткрытьМодально();

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

Переход на метод ОткрытьФорму() и использование ОписаниеОповещения

Разберем базовый шаблон замены модального окна. Нам потребуется создать описание оповещения с помощью объекта ОписаниеОповещения и передать его в метод ОткрытьФорму().


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

&НаКлиенте
Процедура ПослеВыбораКонтрагента(РезультатВыбора, ДополнительныеПараметры) Экспорт
    
    Если ЗначениеЗаполнено(РезультатВыбора) Тогда
        Объект.Контрагент = РезультатВыбора;
    КонецЕсли;
    
КонецПроцедуры

Обратите внимание на ключевой момент: процедура-обработчик результатов (в нашем примере ПослеВыбораКонтрагента) обязательно должна содержать ключевое слово Экспорт.

Установка отборов динамического списка через параметры формы

В управляемом интерфейсе разработчикам не требуется обращаться напрямую к свойствам динамического списка формы до ее открытия. Платформа 1С позволяет передавать отборы через структуру параметров Отбор.

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


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

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

&НаКлиенте
Процедура ПослеВыбораКонтрагентаЗавершение(РезультатВыбора, ДополнительныеПараметры) Экспорт
    
    Если ЗначениеЗаполнено(РезультатВыбора) Тогда
        Объект.Контрагент = РезультатВыбора;
    КонецЕсли;

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

Передача произвольных параметров интерфейса (настройка вида отображения)

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

  1. Передаем произвольный параметр в структуру ПараметрыФормы.
  2. В модуле открываемой формы выбора обрабатываем его в событии ПриСозданииНаСервере.

Код вызова формы из исходного модуля:


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

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

Код в модуле открываемой формы (Справочник.Контрагенты.ФормаВыбора):


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

Блокировка окна владельца без использования модальности

Если требуется запретить пользователю переключаться на основную форму до завершения работы в открывшемся окне, используем параметр РежимОткрытияОкнаФормы:


ОткрытьФорму("Справочник.Контрагенты.ФормаВыбора", 
    ПараметрыФормы, 
    Элемент, 
    Истина, 
    , 
    , 
    Оповещение, 
    РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);

Асинхронный вопрос перед закрытием формы

Частым сценарием при отказе от модальности является вызов диалога подтверждения в событии ПередЗакрытием. Так как код не останавливает исполнение, стандартный метод Вопрос() использовать нельзя. Выясним, как правильно решить эту задачу с помощью ПоказатьВопрос() и флаг-переменной:


&НаКлиенте
Перем ПодтверждениеПолучено;

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

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

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

← На главную