Как организовать открытие формы и ожидание ввода данных перед записью документа?

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

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

Проблема: почему форма закрывается слишком рано?

Когда мы вызываем метод ОткрытьФорму() внутри процедуры ПередЗаписью, платформа выполняет открытие окна и сразу же продолжает выполнение кода. Процедура завершается, и документ записывается (или закрывается), не дожидаясь, пока пользователь что-то введет в открывшемся окне. Наша задача — "поставить на паузу" процесс записи, дождаться ответа пользователя и только потом продолжить.

Решение 1: Классический метод с использованием флага и ОписанияОповещения

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

Шаг 1. Добавление вспомогательного реквизита.

На форму документа необходимо добавить реквизит (не путать с реквизитом самого объекта/документа) с типом Булево. Назовем его, например, ДанныеВведены. По умолчанию он будет равен Ложь.

Шаг 2. Перехват события ПередЗаписью.

Проанализируем код процедуры ПередЗаписью на клиенте. Здесь мы будем проверять наш флаг.


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

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

Шаг 3. Обработка результата в процедуре оповещения.

После того как пользователь заполнит данные и закроет форму, сработает процедура ПослеВводаДанных. Выясним, как правильно вернуть управление основному документу.


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

Решение 2: Современный подход Асинх (платформа 8.3.18+)

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

Разберем пример с использованием метода ОткрытьФормуАсинх():


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

Важные нюансы и рекомендации

Проанализируем несколько критических моментов, которые часто упускают разработчики:

  1. Параметры записи: При повторном вызове метода Записать(ПараметрыЗаписи) крайне важно передавать структуру, полученную в ПередЗаписью. В ней содержатся системные флаги, такие как ЗакрытьПослеЗаписи. Если их проигнорировать, то при нажатии кнопки "Записать и закрыть" форма документа останется висеть на экране после успешной записи.
  2. Режим открытия окна: Чтобы интерфейс выглядел профессионально, всегда используйте РежимОткрытияОкнаФормы.БлокироватьОкноВладельца. Это визуально связывает дочернее окно с основным документом и предотвращает случайные действия пользователя в родительской форме.
  3. Использование ОповеститьОВыборе: В открываемой форме для возврата значения лучше всего вызывать метод ОповеститьОВыборе(Значение). Это обеспечит корректную передачу данных в параметр Результат обработчика оповещения.
  4. Безопасность на сервере: Помните, что клиентские проверки легко обойти (например, при программном проведении документа из списка). Проанализируем ситуацию: если данные критически важны, обязательно продублируйте проверку их заполнения в модуле объекта в серверном обработчике ПередЗаписью, вызывая Отказ = Истина, если данные отсутствуют.

Работа с Библиотекой стандартных подсистем (БСП)

Если вы работаете в типовой конфигурации (УТ 11, ERP, БП 3.0), рекомендуется использовать механизмы БСП. Рассмотрим метод ОбщегоНазначенияКлиент.ПоказатьВопросПользователю или создание специализированных диалогов через подсистему "Работа с формами". Это гарантирует единообразие интерфейса и корректную работу в различных веб-клиентах. При необходимости можно воспользоваться готовой универсальной формой для ввода различных значений.

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

← На главную