Почему не работает ОписаниеОповещения при выборе значения в обычном приложении 1С 8.3?

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

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

Анализ проблемы: почему не срабатывает обратный вызов?

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


&НаКлиенте
Процедура ВыбратьДокументПоступления()
    СобытияФормМДЛПКлиентПереопределяемый.ОткрытьФормуВыбораДокументаПоступлениеТоваров(
        ЭтотОбъект, Объект, Новый ОписаниеОповещения("ПослеВыбораДокументаПоступления", ЭтотОбъект));
КонецПроцедуры

&НаКлиенте
Процедура ПослеВыбораДокументаПоступления(ВыбранныйДокумент, ДополнительныеПараметры) Экспорт
    // Данная процедура должна выполниться после выбора, но вызов не происходит
КонецПроцедуры

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


Процедура ОткрытьФормуВыбораДокументаПоступлениеТоваров(Форма, Объект, ОповещениеПриЗавершении) Экспорт
    ОткрытьФорму("Документ.ПоступлениеТМЦ.ФормаВыбора", , Форма, , , , ОповещениеПриЗавершении);
КонецПроцедуры

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

Критический разбор ошибок и мифов из обсуждения

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

Миф: Процедуру оповещения нужно продублировать в модуле объекта. Некоторые разработчики утверждают, что в обычном приложении процедуру обратного вызова необходимо разместить еще и в модуле объекта (документа или справочника). Это грубейшая техническая ошибка. Объект ОписаниеОповещения работает исключительно в клиентском контексте. Модули объектов всегда выполняются строго на сервере и не поддерживают директиву компиляции &НаКлиенте. Платформа физически не способна вызвать клиентский метод из серверного контекста модуля объекта. Подобные действия лишь засоряют конфигурацию нерабочим кодом.

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

Истинные причины сбоя оповещения в обычном приложении

Выясним настоящие архитектурные причины, из-за которых ломается механизм оповещений при запуске в режиме обычного приложения:

  1. Открываемая форма выбора является Обычной (неуправляемой). Если для документа в конфигурации основной формой выбора назначена обычная форма, то в режиме обычного приложения метод ОткрытьФорму откроет именно ее. Обычные формы «не знают» о существовании механизма ОписаниеОповещения. Платформа просто проигнорирует 7-й параметр метода ОткрытьФорму, и обратного вызова при закрытии или выборе не произойдет.
  2. Форма выбора закрывается без оповещения о выборе. Если форма выбора является управляемой, но разработана вручную, в коде ее закрытия может быть вызван простой метод Закрыть() вместо передачи значения обратно владельцу. Для корректной отработки оповещения форма должна вызывать метод ОповеститьОВыборе() или закрываться с передачей значения, например: Закрыть(ВыбранноеЗначение).
  3. Специфика выполнения в событии ПриОткрытии. Если в открываемой форме в обработчиках ПриСозданииНаСервере или ПриОткрытии срабатывают алгоритмы, которые сразу же принудительно закрывают форму (например, из-за отсутствия прав или параметров), то, начиная с версии платформы 8.3.13, событие оповещения о закрытии не генерируется.

Решение 1: Явное указание управляемой формы выбора

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

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


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

&НаКлиенте
Процедура ОткрытьУправляемуюФормуВыбора(ОповещениеПриЗавершении)
    // Явно прописываем путь к управляемой форме выбора вместо дефолтной
    ОткрытьФорму("Документ.ПоступлениеТМЦ.Форма.ФормаВыбораУправляемая", , ЭтаФорма, , , , ОповещениеПриЗавершении);
КонецПроцедуры

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

При таком подходе платформа гарантированно откроет управляемую форму и привяжет к ней коллбэк-процедуру.

Решение 2: Использование классического механизма владельца формы (Рекомендуется для обычных приложений)

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

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

Шаг 1. Открытие формы выбора с назначением владельца. Нам необходимо открыть форму выбора, передав текущую форму в качестве ее владельца (это 3-й параметр метода ОткрытьФорму):


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

Шаг 2. Реализация обработчика события в форме-приемнике. В модуле вызывающей управляемой формы создаем стандартный обработчик события ОбработкаВыбора. Именно сюда платформа перенаправит выбранное значение, независимо от того, обычная или управляемая форма использовалась для выбора:


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

&НаКлиенте
Процедура ВыполнитьОбработкуВыбранногоДокумента(ДокументСсылка)
    // Здесь располагается ваша прикладная логика
    Если ИнтеграцияМДЛПВызовСервера.ЕстьРасхожденияМеждуУведомлениемИОснованием(Объект.Ссылка, ДокументСсылка) Тогда
        // Реализация дополнительного диалога с пользователем
    КонецЕсли;
КонецПроцедуры

Использование этого способа полностью исключает проблемы совместимости клиентского контекста разных типов форм.

Решение 3: Проверка кода в форме выбора

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

Убедитесь, что выбор значения в форме завершается вызовом метода ОповеститьОВыборе. Посмотрим, как это должно быть реализовано в форме выбора:


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

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

Резюме

Для стабильной работы интерфейса в смешанных режимах запуска 1С (режим обычного приложения с использованием управляемых форм) придерживайтесь следующих правил:

← На главную