Взаимодействие с пользователем в 1С 8.3: предупреждения, вопросы и собственные формы
Содержание
Диалог с пользователем в 1С 8.3 собирают из четырёх групп методов встроенного языка: вывод сообщений (Сообщить, ПоказатьПредупреждение), вопросы с выбором (ПоказатьВопрос), запрос значений (ПоказатьВводЧисла, ПоказатьВводСтроки и другие) и открытие собственной формы через ОткрытьФорму. Всё это работает на клиенте.
Главная особенность платформы 8.3 — диалоги по умолчанию асинхронные. Метод не останавливает код и не возвращает ответ прямо в точке вызова: результат приходит в отдельный обработчик оповещения. Если держать это в голове, остальное складывается быстро.
Ниже — каждый способ с рабочим примером: от всплывающего уведомления до формы с возвратом выбранного значения и передачей параметров.
Все вызовы ниже выполняются на клиенте, поэтому процедуры помечены директивой &НаКлиенте. Данные для диалога (список значений, параметры структуры) можно подготовить на сервере и передать на клиент, но само окно всегда поднимает клиентский код.
Сообщения и всплывающие уведомления
Самый частый случай — сообщить пользователю факт: документ проведён, проверка не прошла, настройка сохранена. Для этого есть несколько инструментов разного «веса».
Сообщение в нижней части формы. Текст появляется под формой, может быть привязан к конкретному полю реквизита — удобно для валидации.
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Заполните контрагента";
Сообщение.Поле = "Объект.Контрагент";
Сообщение.УстановитьДанные(Объект);
Сообщение.Сообщить();
Короткая форма Сообщить("Текст") тоже работает и осталась для совместимости, но без привязки к полю — просто строка в общей ленте сообщений.
Всплывающее предупреждение. Отдельное окно с кнопкой «ОК». В 8.3 используйте асинхронный ПоказатьПредупреждение — он не блокирует интерфейс и работает в веб-клиенте:
ПоказатьПредупреждение(, "Операция завершена", 5, "Готово");
Первый параметр — описание оповещения о завершении (чаще не нужен), затем текст, таймаут в секундах и заголовок окна.
Ненавязчивое оповещение. Всплывает в правом нижнем углу и само исчезает — не требует реакции:
ПоказатьОповещениеПользователя("Записано", , "Документ сохранён");
Для обычного информирования берите оповещение или сообщение под формой — они не прерывают работу. Модальное окно Предупреждение() оставьте для случаев, когда пользователь обязан увидеть текст.
Вопрос с выбором: подтверждение действий
Перед необратимой операцией (удаление, перепроведение, очистка) спрашивают подтверждение. За это отвечает ПоказатьВопрос. Набор кнопок задаёт тип РежимДиалогаВопрос, а нажатую кнопку вы разбираете по значению КодВозвратаДиалога.
&НаКлиенте
Процедура УдалитьСтроку(Команда)
Оповещение = Новый ОписаниеОповещения("ПослеВопросаОбУдалении", ЭтотОбъект);
ПоказатьВопрос(Оповещение, "Удалить выделенную строку?", РежимДиалогаВопрос.ДаНет);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВопросаОбУдалении(Результат, ДополнительныеПараметры) Экспорт
Если Результат = КодВозвратаДиалога.Да Тогда
// здесь удаляем строку
КонецЕсли;
КонецПроцедуры
Код после вызова ПоказатьВопрос выполняется сразу, не дожидаясь ответа. Всю реакцию на выбор пишите только в процедуре-обработчике, имя которой передали в ОписаниеОповещения.
Доступные наборы кнопок:
| Режим | Кнопки | Когда применять |
|---|---|---|
ДаНет | Да · Нет | простое подтверждение |
ДаНетОтмена | Да · Нет · Отмена | есть третий вариант — отказаться вовсе |
ОКОтмена | ОК · Отмена | согласие с возможностью передумать |
ПовторитьОтмена | Повторить · Отмена | после сбоя предложить повтор |
Если нужны нестандартные надписи на кнопках, вместо РежимДиалогаВопрос передайте СписокЗначений: значение станет кодом возврата, а представление — текстом кнопки.
Кнопки = Новый СписокЗначений;
Кнопки.Добавить("Провести", "Провести и закрыть");
Кнопки.Добавить("Черновик", "Сохранить как черновик");
Кнопки.Добавить("Отмена", "Вернуться к документу");
ПоказатьВопрос(Оповещение, "Что сделать с документом?", Кнопки);
В обработчике тогда сравнивайте результат не с КодВозвратаДиалога, а со значениями, которые вы положили в список: Если Результат = "Провести" Тогда. Так из одного вопроса получается три осмысленных варианта вместо сухого «Да/Нет».
Запрос данных: число, строка, дата
Когда от пользователя нужно получить одно значение, не поднимая отдельную форму, подойдут методы ввода. Все они асинхронные и возвращают результат в обработчик оповещения.
&НаКлиенте
Процедура ВвестиКоличество(Команда)
Оповещение = Новый ОписаниеОповещения("ПослеВводаКоличества", ЭтотОбъект);
ПоказатьВводЧисла(Оповещение, 0, "Укажите количество", 10, 0);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВводаКоличества(Число, ДополнительныеПараметры) Экспорт
Если Число <> Неопределено Тогда
// пользователь ввёл значение и нажал ОК
КонецЕсли;
КонецПроцедуры
Параметры ПоказатьВводЧисла — описание оповещения, начальное значение, подсказка, длина и точность. Аналогично устроены соседи:
- 🔢
ПоказатьВводЧисла— число с заданной точностью; - 🔤
ПоказатьВводСтроки— строка, можно включить многострочный режим; - 📅
ПоказатьВводДаты— дата или дата со временем; - 📋
ПоказатьВводЗначения— значение заданного типа или выбор изСписокЗначений.
Если пользователь закрыл окно крестиком или нажал «Отмена», в обработчик придёт Неопределено. Проверяйте это перед тем, как использовать значение, иначе получите ошибку на пустом результате.
ПоказатьВводЗначения удобен, когда выбор ограничен справочником или заранее известным перечнем — пользователь не вводит текст руками, а выбирает из предложенного, и опечатки исключены. Тип значения задают описанием типов:
&НаКлиенте
Процедура ВыбратьНоменклатуру(Команда)
Оповещение = Новый ОписаниеОповещения("ПослеВыбораНоменклатуры", ЭтотОбъект);
ОписаниеТипа = Новый ОписаниеТипов("СправочникСсылка.Номенклатура");
ПоказатьВводЗначения(Оповещение, Неопределено, "Выберите товар", ОписаниеТипа);
КонецПроцедуры
Пользователь получит поле с кнопкой выбора, за которой откроется форма списка справочника — отдельную форму выбора писать не придётся.
Собственная форма вместо стандартного диалога
Стандартных окон хватает для одного-двух значений. Как только нужно несколько полей, проверки при вводе или выбор из таблицы — делайте собственную форму. Обычно это общая форма конфигурации, которую открывают как модальное окно поверх владельца.
&НаКлиенте
Процедура ВыбратьПериод(Команда)
ОписаниеЗакрытия = Новый ОписаниеОповещения("ПослеВыбораПериода", ЭтотОбъект);
ОткрытьФорму("ОбщаяФорма.ВыборПериода", , ЭтотОбъект, , , ,
ОписаниеЗакрытия, РежимОткрытияОкна.БлокироватьОкноВладельца);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораПериода(Результат, ДополнительныеПараметры) Экспорт
Если Результат <> Неопределено Тогда
НачалоПериода = Результат.Начало;
КонецЕсли;
КонецПроцедуры
Чтобы форма вернула значение, в ней при нажатии «ОК» вызывают Закрыть с нужным результатом — он и придёт в обработчик закрытия владельца:
&НаКлиенте
Процедура ОК(Команда)
Результат = Новый Структура("Начало, Конец", ДатаНачала, ДатаКонца);
Закрыть(Результат);
КонецПроцедуры
Режим БлокироватьОкноВладельца не даёт работать с исходной формой, пока диалог открыт, но при этом не блокирует всё приложение — это современная замена устаревшему модальному открытию.
Есть и второй способ вернуть значение — через механизм выбора. В форме диалога вызывают ОповеститьОВыборе(Значение), а у владельца срабатывает стандартный обработчик ОбработкаВыбора:
// у формы-владельца
&НаКлиенте
Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора) Экспорт
ВыбраннаяСтавка = ВыбранноеЗначение;
КонецПроцедуры
Этот вариант уместен, когда одна форма служит источником выбора для нескольких владельцев. Для разового диалога «открыл — получил ответ» проще описание оповещения о закрытии: вся логика остаётся в одной процедуре, и не нужно заводить общий обработчик ОбработкаВыбора.
Параметры диалога и передача данных в форму
Диалог редко открывают «пустым»: в него передают исходные значения, а поведение настраивают параметрами.
Передача данных в форму. Второй аргумент ОткрытьФорму — структура параметров. Форма читает их при создании:
// при открытии
Параметры = Новый Структура("Организация, Дата", ВыбраннаяОрганизация, ТекущаяДата());
ОткрытьФорму("ОбщаяФорма.Настройки", Параметры, ЭтотОбъект);
// в открываемой форме
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если Параметры.Свойство("Организация") Тогда
Организация = Параметры.Организация;
КонецЕсли;
КонецПроцедуры
Проверка через Свойство страхует от ситуации, когда форму открыли без параметра.
Настройка стандартных диалогов. У ПоказатьВопрос и ПоказатьПредупреждение есть полезные параметры:
- ⏱ Таймаут — через сколько секунд окно закроется само. Удобно, когда ответ не критичен;
- ✅ КнопкаПоУмолчанию — какая кнопка активна при нажатии Enter;
- 🏷 Заголовок — текст в шапке окна вместо стандартного.
ПоказатьВопрос(Оповещение, "Продолжить?", РежимДиалогаВопрос.ДаНет,
15, КодВозвратаДиалога.Нет, "Подтверждение");
Здесь окно закроется через 15 секунд, по умолчанию выделена «Нет» — безопасный вариант, если пользователь просто нажмёт Enter не читая.
Модальность, асинхронность и прерывание ввода
В платформе 8.3 диалоги работают в двух режимах. Модальный (Вопрос, Предупреждение, ВвестиЧисло) останавливает выполнение и возвращает ответ прямо в строке вызова, но недоступен в веб-клиенте и считается устаревшим. Асинхронный (ПоказатьВопрос, ПоказатьПредупреждение, ПоказатьВводЧисла) не блокирует интерфейс и работает везде.
Режим задаётся свойством конфигурации Режим использования модальности в Конфигураторе. Для новых решений ставьте значение Не использовать — платформа при сборке подскажет все места, где остались модальные вызовы.
Синтаксис Асинх/Ждать. Начиная с версии платформы не ниже 8.3.18, асинхронный код можно писать линейно, без отдельных обработчиков:
&НаКлиенте
Асинх Процедура УдалитьСтрокуАсинх(Команда)
Ответ = Ждать ВопросАсинх("Удалить строку?", РежимДиалогаВопрос.ДаНет);
Если Ответ = КодВозвратаДиалога.Да Тогда
// удаляем
КонецЕсли;
КонецПроцедуры
Оператор Ждать приостанавливает только эту процедуру, не замораживая интерфейс. Читается как обычный последовательный код — это удобнее цепочек из описаний оповещений.
Прерывание пользователем. Любой диалог можно закрыть, не выбрав ответ. Для вопросов это КодВозвратаДиалога.Отмена, для методов ввода — Неопределено. Отдельную ветку «пользователь отказался» в обработчике стоит предусматривать всегда, иначе цепочка диалогов оборвётся с ошибкой.
Если речь о долгой операции в цикле, а не о диалоге, прерывание обрабатывают иначе — методом ОбработкаПрерыванияПользователя(). Вызов внутри цикла даёт платформе шанс отреагировать на команду остановки, которую пользователь подал с клавиатуры.
Когда диалог лучше не показывать
Диалог прерывает работу, и злоупотребление им раздражает пользователя сильнее, чем помогает. Несколько ситуаций, где окно стоит заменить на что-то тише:
- Валидация заполнения. Вместо вопроса «Вы не указали контрагента, продолжить?» привяжите сообщение к полю через
СообщениеПользователюи установитеОтказ = Истинав проверке. Пользователь увидит подсветку поля прямо на форме. - Подтверждение каждого шага. Если спрашивать согласие на каждое действие, пользователь привыкает жать «Да» не читая. Подтверждение нужно только перед необратимыми операциями.
- Информирование об успехе. «Документ записан» уместнее показать ненавязчивым оповещением в углу, а не окном с «ОК», которое приходится закрывать руками.
Хорошее правило: модальное окно оправдано там, где цена ошибки высока — удаление, перепроведение, выгрузка. В остальных случаях выбирайте сообщение под формой или всплывающее оповещение.
Типичные ошибки при работе с диалогами
Разбор частых граблей — отдельно от шагов выше, чтобы не искать их по тексту.
- 🚫 Логика сразу после
Показать…. Код не ждёт ответа. Строки, которые должны выполниться после выбора, перенесите в обработчик оповещения — иначе они сработают до того, как пользователь нажмёт кнопку. - 🚫 Модальный метод в веб-клиенте.
Вопрос,Предупреждение,ВвестиСтрокувызовут ошибку, если модальность отключена. Используйте асинхронные аналоги илиАсинх/Ждать. - 🚫 Нет проверки на
Неопределено. После ввода значения пользователь мог нажать «Отмена». Обращение к полям пустого результата приведёт к ошибке выполнения. - 🚫 Обработчик на сервере.
ОписаниеОповещениядля диалогов указывает на клиентскую процедуру. Серверный обработчик платформа не вызовет — диалоги живут только на клиенте. - 🚫 Структура параметров не проверена. В открываемой форме читайте параметры через
Параметры.Свойство("Имя"), иначе при открытии без параметра получите ошибку обращения к несуществующему свойству.
Чем `ПоказатьВопрос` отличается от `Вопрос`?
Вопрос — модальный: останавливает код и возвращает ответ в точке вызова, но не работает в веб-клиенте. ПоказатьВопрос — асинхронный: ответ приходит в обработчик оповещения, зато работает во всех клиентах. В 8.3 выбирайте второй.Как получить результат из собственной формы?
Закрыть(Результат), а при открытии передайте в ОткрытьФорму описание оповещения о закрытии. Значение из Закрыть придёт в указанный обработчик владельца.Что вернётся, если пользователь закрыл окно крестиком?
Неопределено. Для ПоказатьВопрос результат зависит от набора кнопок, но отдельной кнопки «Отмена» там может и не быть; надёжнее проверять конкретный КодВозвратаДиалога, который вы ждёте.Можно ли писать диалоги линейно, без обработчиков?
Асинх-процедуры и оператор Ждать с методами вида ВопросАсинх. Нужна платформа версии не ниже 8.3.18 и ключевое слово Асинх перед объявлением процедуры.Как задать свои надписи на кнопках вопроса?
РежимДиалогаВопрос передайте в ПоказатьВопрос объект СписокЗначений: значение каждого элемента станет кодом возврата, а представление — текстом на кнопке.