Как открыть форму и получить из неё значение без использования модального режима

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

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

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

Способ 1: Механизм оповещения о выборе (ОбработкаВыбора)

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

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

В вызывающей форме (Владельце):

При использовании метода ОткрытьФорму мы должны передать текущую форму в качестве четвертого параметра (параметр Владелец).


&НаКлиенте
Процедура ОткрытьФормуВыбора(Команда)
    // Передаем "ЭтаФорма" как владельца
    ОткрытьФорму("Обработка.МояОбработка.Форма.ФормаМоейОбработки", , ЭтаФорма);
КонецПроцедуры

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


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

В открываемой форме:

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


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

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

Способ 2: Использование ОписанияОповещения (Callback)

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

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

В вызывающей форме:

  1. Создаем объект ОписаниеОповещения.
  2. Передаем его в метод ОткрытьФорму.

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

&НаКлиенте
Процедура ПослеЗакрытияФормыВыбора(Результат, ДополнительныеПараметры) Экспорт
    
    // Если результат не равен Неопределено, значит пользователь что-то выбрал
    Если Результат <> Неопределено Тогда
        Сообщить("Получено значение: " + Результат);
    КонецЕсли;
    
КонецПроцедуры

В открываемой форме:

В этом сценарии нам не нужно использовать ОповеститьОВыборе. Мы просто закрываем форму, передавая результат выбора непосредственно в метод Закрыть().


&НаКлиенте
Процедура ЗавершитьВыборИЗакрыть(Команда)
    Результат = "Данные, которые мы хотим вернуть";
    Закрыть(Результат);
КонецПроцедуры

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

Способ 3: Механизм Оповестить() и ОбработкаОповещения

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

Разберем пример реализации:

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

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

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

Сравнение методов: что выбрать?

Выясним, какой из методов лучше подходит для ваших задач:

Рекомендация по передаче контекста

Поскольку немодальное открытие не останавливает выполнение кода (строки, идущие после ОткрытьФорму, выполнятся мгновенно), важно правильно сохранять контекст. Если до момента выбора пользователя вам нужны были какие-то локальные переменные, упакуйте их в структуру ДополнительныеПараметры при создании ОписанияОповещения. Это позволит вам получить их обратно в процедуре обработки результата и продолжить работу так, как будто паузы не было.

Посмотрим на пример с контекстом:


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

&НаКлиенте
Процедура ЗавершитьСложныйПроцесс(Результат, ДополнительныеПараметры) Экспорт
    // Здесь ДополнительныеПараметры содержат наш контекст
    Стадия = ДополнительныеПараметры.ТекущаяСтадия;
    // Продолжаем логику...
КонецПроцедуры

Использование этих подходов позволит вам создавать современные, быстрые и надежные интерфейсы в 1С, полностью соответствующие стандартам разработки на платформе 8.3.

← На главную