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