Почему не выводится сообщение через Сообщить() после вызова модального окна ВвестиЗначение()?

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

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

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


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

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

Решение 1: Проверка на ошибку в платформе 1С

Как ни странно, именно этот редкий случай оказался решением в исходной проблеме на форуме. Автор выяснил, что такое поведение было вызвано ошибкой в конкретной версии платформы — 8.3.15.1656. После перехода на другую версию (в его случае, более старую 8.3.6.2530, но и более новые версии, скорее всего, лишены этой ошибки) проблема исчезла, и сообщение стало выводиться корректно.

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

Решение 2: Проверка логики условия и отказ от ввода

Функция ВвестиЗначение() является модальной и возвращает булево значение:

В коде автора вызов Сообщить() находится внутри условия Если ... Тогда. Это означает, что сообщение будет выведено, только если пользователь подтвердил ввод. Если он отменил операцию, код внутри условия просто не выполнится, и сообщения не будет. Это абсолютно нормальное поведение.

Убедитесь, что вы действительно выбираете значение и нажимаете "ОК" при тестировании. Если нужно, чтобы какая-то логика выполнялась и при отмене, ее следует вынести в блок Иначе.


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

Решение 3: Проверка режима использования модальности

Это одна из самых частых причин проблем с модальными окнами в современных конфигурациях. Платформа 1С движется в сторону отказа от модальности, особенно для веб-клиента. В свойствах конфигурации есть специальная настройка:

Свойства конфигурации -> Основные -> Режим использования модальности

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

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

Решение 4: Современный асинхронный подход (рекомендуемый)

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

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

Давайте перепишем исходный код с использованием асинхронного аналога ВвестиЗначение() — функции ПоказатьВводЗначения().

  1. Создадим процедуру-обработчик, которая выполнится после ввода значения. Она будет принимать результат ввода в качестве первого параметра. Важно, чтобы эта процедура была экспортной.

  2. В основной процедуре создадим ОписаниеОповещения, которое будет ссылаться на нашу процедуру-обработчик.

  3. Вызовем ПоказатьВводЗначения(), передав в него это оповещение.

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


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

    // 2. Вызываем немодальное окно ввода значения.
    // Код после этой строки продолжит выполняться сразу, не дожидаясь ввода.
    ПоказатьВводЗначения(Оповещение, , "Выберите документ", Тип("ДокументСсылка.РасходныеНакладные"));
КонецПроцедуры

// 3. Та самая процедура-обработчик, которая вызовется после закрытия окна ввода.
// Она ОБЯЗАТЕЛЬНО должна быть с ключевым словом "Экспорт".
&НаКлиенте
Процедура ВыбратьДокументЗавершение(ВыбранныйДокумент, ДополнительныеПараметры) Экспорт
    // Если пользователь нажал "Отмена", то параметр ВыбранныйДокумент будет "Неопределено".
    // Это аналог проверки "Если ВвестиЗначение(...) Тогда".
    Если ВыбранныйДокумент <> Неопределено Тогда
        Сообщить("Выбран документ: " + ВыбранныйДокумент);
        
        // Либо можно использовать более современный аналог Сообщить()
        ПоказатьОповещениеПользователя("Документ выбран!", , "Выбран документ: " + ВыбранныйДокумент);
    Иначе
        Сообщить("Выбор документа был отменен.");
    КонецЕсли;
КонецПроцедуры

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

Использование асинхронных вызовов — это не просто альтернатива, а стандарт разработки для современных конфигураций 1С. Этот подход решает проблемы с блокировкой интерфейса, корректно работает во всех клиентах (включая веб) и позволяет избежать странных ошибок платформы, связанных с потерей контекста после закрытия модальных окон.

← На главную