Как открыть другую форму документа из модуля команды в 1С и сделать ее модальной?

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

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

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

Причина открытия пустой формы и использование параметра «Ключ»

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

В модуле команды обработчик принимает два параметра: ПараметрКоманды (который содержит ссылку на текущий документ) и ПараметрыВыполненияКоманды (контекст вызова). Выясним, как правильно составить структуру параметров для открытия формы:


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

Благодаря параметру Ключ платформа автоматически считает объект из базы данных и заполнит все реквизиты в открываемой форме «ДругойГород».

Как заблокировать окно владельца (эмуляция модального режима)

В современных конфигурациях 1С использование метода ОткрытьФормуМодально() запрещено из-за требований кроссплатформенности и работы в веб-клиенте. Чтобы открыть дополнительную форму поверх основной и заблокировать интерфейс родительского окна, следует использовать механизм блокировки окна владельца.

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

Рассмотрим пример кода, реализующий блокирующий режим работы:


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

При таком подходе окно откроется как вспомогательное и заблокирует доступ к основной форме документа «Заказ», пока пользователь не закроет дополнительную форму.

Настройка свойств формы в Конфигураторе

Если вы хотите избежать написания громоздкого программного кода при каждом вызове, настройки отображения окна можно задать непосредственно в свойствах самой формы «ДругойГород» в конфигураторе:

  1. Откройте форму «ДругойГород» в дереве метаданных.
  2. Перейдите в палитру свойств формы.
  3. Найдите свойство Режим открытия окна и установите для него значение Блокировать окно владельца.
  4. Убедитесь, что свойство Вариант открытия окна настроено на открытие во вспомогательном окне (а не в новой вкладке).

После этого при обычном вызове метода ОткрытьФорму("Документ.Заказ.Форма.ДругойГород", ПараметрыФормы, ЭтотОбъект) окно автоматически примет нужный вид и заблокирует родительскую форму.

Важный нюанс: Работа с незаписанными изменениями

Поскольку при передаче параметра Ключ система считывает данные объекта непосредственно из базы данных, вы можете столкнуться со следующей проблемой: если пользователь открыл основную форму заказа, изменил комментарий или состав табличной части, но не нажал кнопку «Записать», то при открытии дополнительной формы через команду изменения отображены не будут. Форма отобразит только те данные, которые были сохранены в БД на текущий момент.

Разберем два возможных способа решения этой проблемы:

Способ 1. Принудительная запись объекта перед открытием

Перед вызовом вспомогательной формы мы можем проверить свойство модифицированности основной формы и записать объект, если в него вносились изменения:


// Пример кода, выполняемого на клиенте в модуле формы
Если Модифицированность Тогда
    // Записываем форму, чтобы актуализировать данные в базе
    Записать(); 
КонецЕсли;

ПараметрыФормы = Новый Структура("Ключ", Объект.Ссылка);
ОткрытьФорму("Документ.Заказ.Форма.ДругойГород", ПараметрыФормы, ЭтотОбъект);

Способ 2. Программное копирование данных формы без записи в БД

Если записывать документ в базу данных преждевременно нельзя, мы можем программно получить новую форму на сервере и скопировать в нее текущее состояние данных из формы-источника без обращения к СУБД:


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

&НаСервереБезКонтекста
Процедура КопироватьДанныеНаСервере(ФормаИсточник, НоваяФорма)
    // Метод копирует структуру данных реквизита "Объект"
    КопироватьДанныеФормы(ФормаИсточник.Объект, НоваяФорма.Объект);
КонецПроцедуры

Возврат измененных данных из вспомогательной формы

В случае, если пользователь изменил реквизит (например, тот самый «СуперРеквизит») в упрощенной форме и закрыл её, нам нужно передать это новое значение обратно в основную форму. Так как мы отказались от модальности, код вызывающей процедуры не ждет закрытия формы. Для получения обратной связи используем механизм оповещений (ОписаниеОповещения).

Посмотрим на пример реализации возврата данных:


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

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

Во вспомогательной форме при закрытии (например, по нажатию кнопки «ОК» или «Сохранить») следует вызвать метод закрытия с передачей структуры результата:


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

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

← На главную