Модальный диалог в 1С

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

Общая информация

В начале рассмотрим общие вопросы связанные с модальными окнами в 1С.

Что не так с модальными окнами?

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

Все это прекрасно работает в тонком и толстом клиенте и с большим трудом в веб-клиенте. Современные браузеры как правило поддерживают модальные окна (какие-то лучше, какие-то хуже) — открывая их в новом окне как «всплывающее окно». Но из-за того, что всплывающие окна используются в основном для рекламы, их показ отключен по умолчанию практических во всех современных браузерах. Следовательно, в подавляющем большинстве случаев необходима предварительная настройка браузера.

Когда следует отказаться от модальности?

Разумеется отказ от модальности необходим далеко не всегда.

Во-первых, режим работы интерфейса без использования модальности появился в версии технологической платформы 8.3.3.721 (от 06.09.2013) — следовательно, при использовании предыдущих версий технологической платформы, не нужно задумываться об отказе от модальности.

Режим использования модальности

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

  • на iPad;
  • через веб-клиент;
  • в режиме сервиса (например, размещенные на 1cfresh.com).

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

Как все поправить?

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

Каждый раз, перед тем как начать переделывать модальный диалог, стоит очень серьезно подумать — не проще ли будет избавиться от этого диалога совсем.

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

Непосредственно при отказе от модальности очень поможет механизм рефакторинга о котором подробно написано в отдельной статье.

Соответствие синхронных методов асинхронным аналогам (на момент написания статьи) можно посмотреть .

Практические примеры

В качестве практических примеров рассмотрим основные приемы работы с блокирующими окнами.

Работа с блокирующими окнами

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 &НаКлиенте Процедура Спросить() //создаем описание оповещения ОбратныйВызов = Новый ОписаниеОповещения(«ОбработкаОтвета», ЭтотОбъект); Если Модифицированность Тогда ПоказатьВопрос(ОбратныйВызов, «Данные были изменены. Записать изменения?», РежимДиалогаВопрос.ДаНет); Иначе //мы можем выполнить обработку оповещения //в этом случае РезультатВопрос = Неопределено ВыполнитьОбработкуОповещения(ОбратныйВызов); //в том числе с заданным результатом ВыполнитьОбработкуОповещения(ОбратныйВызов, КодВозвратаДиалога.Да); КонецЕсли; КонецПроцедуры &НаКлиенте Процедура ОбработкаОтвета(РезультатВопроса, ДополнительныеПараметры) Экспорт Если РезультатВопроса = КодВозвратаДиалога.Да Тогда Сообщить(«Данные записаны»); ИначеЕсли РезультатВопроса = КодВозвратаДиалога.Нет Тогда Сообщить(«Данные не записаны»); ИначеЕсли РезультатВопроса = Неопределено Тогда Сообщить(«Данные не были изменены»); КонецЕсли; КонецПроцедуры

Блокирующие окна и закрытие приложения

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

Кроме этого, в обработчике события формы ПередЗакрытием и в обработчике события управляемого приложения ПередЗавершениемРаботыСистемы реализован параметр ТекстПредупреждения.

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

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 &НаКлиенте Процедура ОткрытьФормуТест(Команда) ОбработкаЗакрытия = Новый ОписаниеОповещения(«ОбработкаЗакрытияФормы», ЭтотОбъект); //открываем общую форму в блокирующем режиме ОткрытьФорму(«ОбщаяФорма.Форма»,,,,,,ОбработкаЗакрытия, РежимОткрытияОкнаФормы.БлокироватьВесьИнтерфейс); //завершаем работу всего приложения ЗавершитьРаботуСистемы(); //в этом случае приложение закроется не задавая никаких вопросов //ЗавершитьРаботуСистемы(Ложь); КонецПроцедуры &НаКлиенте Процедура ОбработкаЗакрытияФормы(РезультатЗакрытия, ДополнительныеПараметры) Экспорт Сообщить(«Форма закрыта»); КонецПроцедуры

Затем в модуле открытой формы выясняем, что закрывается не сама форма, а все приложение и пытаемся предотвратить это:

1 2 3 4 5 6 7 8 9 10 11 12 13 &НаКлиенте Процедура ПередЗакрытием(Отказ, ЗавершениеРаботы, ТекстПредупреждения, СтандартнаяОбработка) //флаг завершения работы приложения Если ЗавершениеРаботы Тогда //пробуем вывести сообщение для пользователя Отказ = Истина; ТекстПредупреждения = «Закрывать приложение нельзя»; КонецЕсли; КонецПроцедуры

Результат будет выглядеть примерно так:

Обработка закрытия приложения

На этом все, надеюсь, что эта статья была Вам полезна.

Если Вы нашли ошибку или неточность, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Вызывается при поступлении в форму оповещения, отправленного методом Оповестить() из другой формы

Синтаксис

Предопределенная процедура ОбработкаОповещения() имеет следующий синтаксис:

ОбработкаОповещения(ИмяСобытия, Параметр, Источник)

А также альтернативный англоязычный синтаксис:

NotificationProcessing(EventName, Paramener, Source)

Параметры

Описание параметров процедуры ОбработкаОповещения():

Имя параметра Тип Описание
ИмяСобытия Строка Переданное имя события. Может быть использовано для идентификации сообщений.
Параметр Произвольный Произвольные данные
Источник Произвольный Источник события, например, другая форма или элемент управления.
Жирным шрифтом выделены обязательные параметры

Описание

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

Доступность

Толстый клиент, Тонкий клиент, Веб-клиент

Пример использования

Пример кода с использованием процедуры ОбработкаОповещения():

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

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

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

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

Как устранить ошибку в 1С: «Использование модальных окон в данном режиме запрещено»

Такая ошибка начала появляться после перехода 1С на новый интерфейс платформы 1С 8.3 – «Такси». Это связано с тем, что в ней разработчиками была включена работа с окнами, но без режима модальности.

Рис.1 Предупреждение

Откроем информационную базу в режиме «Конфигуратор» и посмотрим свойства нашей конфигурации, нажав правой кнопкой мышки и выбрав команду «Свойства». Прокрутив линейку ниже, мы видим раздел «Совместимость», где находится интересующий нас параметр режима и перечислены варианты – «Использовать/Использовать с предупреждением/Не использовать».

Рис.2 Выбор режима

После этого необходимо сохранить и обновить изменения в конфигурации. Ошибка, о которой мы говорим, появляется, когда стоит отметка о том, чтобы не использовать режим модальности. Такая возможность появилась, начиная с платформы 8.3.3.721, вышедшей в сентябре 2013 года. То есть, пользователям, работающим на более старых версиях платформы, нет необходимости в отказе от модальности. В других версиях, чтобы окно с ошибкой не появлялось, можно установить просто – «Использовать».

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

Рис.3 Служебное сообщение

Приложения, которые используются через веб-клиент, на iPad, в облаке, например, на «1cfresh.com», не используют этот режим. Во всех новых конфигурациях используется безмодальный режим работы интерфейса.

Отказ от модальности

Разработчики программы 1С, а также компании, оказывающие услуги франчайзи 1С, поддерживая общемировые тенденции, стараются приблизить интерфейс программ к веб-образцам и привести его к единому стандарту, давая тем самым возможность пользователям работать в одном окне с привычном «внешником».

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

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

В интернете есть много примеров, где используется глобальная переменная и метод удаление вызывается два раза, первый раз для вопроса пользователю, а второй непосредственно для удаления. Этот вариант мне показался сильно замудренный.
Для демонстрации создадим чистую конфигурацию. В свойствах конфигурации проверяем факт отключения режима модальности.
Создадим документ с именем Документ1. В объекте Документ1 добавим табличную часть с именем ТабличнаяЧасть1. В этой табличной части для демонстрации добавляем реквизит Реквизит1 с типом Строка длинной 10 символов.
Создаем форму документа, для табличной части ТабличнаяЧасть1 создаем событие ПередУдалением(Элемент, Отказ).
В данное событие прописываем код, где в первую очередь отказываемся от стандартной процедуры удаления: Отказ = Истина;
Далее создаем оповещение на процедуру УдалениеСтроки с передачей одного параметра, который содержит текущий элемент коллекции ДанныеФормыКоллекция (Элементы.ТабличнаяЧасть1.ТекущиеДанные). Код оповещения получился таким:
Оповещение = Новый ОписаниеОповещения(«УдалениеСтроки», ЭтотОбъект, Элементы.ТабличнаяЧасть1.ТекущиеДанные); Далее показываем вопрос пользователю:ПоказатьВопрос(Оповещение, «Удалить?», РежимДиалогаВопрос.ДаНет); В результате получили процедуру с кодом:
&НаКлиенте Процедура ТабличнаяЧасть1ПередУдалением(Элемент, Отказ) Отказ = Истина; Оповещение = Новый ОписаниеОповещения(«УдалениеСтроки», ЭтотОбъект, Элементы.ТабличнаяЧасть1.ТекущиеДанные); ПоказатьВопрос(Оповещение, «Удалить?», РежимДиалогаВопрос.ДаНет); КонецПроцедуры На стороне клиента создаем экспортную процедуру УдалениеСтроки(Результат, ДополнительныеПараметры).
Сначала проверяем, что нажал пользователь Да или Нет. Если пользователь нажал кнопку Да, то строчкой кода Объект.ТабличнаяЧасть1.Удалить(ДополнительныеПараметры); удаляем из коллекции ДанныеФормыКоллекция текущий элемент переданный в параметр ДополнительныеПараметры.
После строки удаления прописываем код установки факта Модифицированности: Модифицированность = Истина;
В результате получили процедуру с кодом: &НаКлиенте Процедура УдалениеСтроки(Результат, ДополнительныеПараметры) Экспорт Если Результат = КодВозвратаДиалога.Да Тогда Объект.ТабличнаяЧасть1.Удалить(ДополнительныеПараметры); Модифицированность = Истина; КонецЕсли; КонецПроцедуры Результат полного кода представлен на рисунке ниже.

В 1С предполагается, что СообщениеПользователю выводятся для того, чтобы сообщить пользователю об ошибках.

А для информирования о выполняемом действии рекомендуется использовать метод встроенного языка ПоказатьОповещениеПользователя().

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

Пример вывода сообщения на клиенте:

Код 1C v 8.3 Если ЗначениеЗаполнено(объект.ИнтернетМагазин) Тогда

// Все заполнено, обрабатываем
Иначе
сбп=Новый СообщениеПользователю;
сбп.Текст = «Укажите интернет-магазин данные которого Вы загружаете!»;
сбп.Поле=»ИнтернетМагазин»;
сбп.ПутьКДанным = «Объект»;
сбп.Сообщить();
КонецЕсли;

При обработке на сервере:

Необходимо зарегистрировать в системе соответствие объекта и имени реквизита формы. Для этого в глобальном контексте реализована функция УстановитьСоответствиеОбъектаИРеквизитаФормы(). Сделать это можно следующим образом:

Код 1C v 8.3 &НаСервере
Процедура ПроцедураВызываемаяСКлиента(ОбъектДанных)
Документ = ДанныеФормыВЗначение(Объект, Тип(«ДокументОбъект.ПоступлениеТМЦ»)); // Преобразования данных формы в объект
УстановитьСоответствиеОбъектаИРеквизитаФормы(Документ, «Объект»); // Установка соответствия
ДействиеСОбъектом(Документ); // Действия над объектом, в процессе работы которых может возникнуть необходимость вывода сообщений
КонецПроцедуры

В данном фрагменте выполняется преобразование объекта из данных формы в реальный объект и устанавливается его соответствие с реквизитом формы по имени «Объект».

Если в дальнейшем требуется создать сообщение, можно сделать это следующим образом:

Код 1C v 8.3 &НаСервере
Процедура ДействиеСОбъектом(ОбъектДанных)
// Какие либо действия, которые требуют создания сообщения
// Создание сообщения
Сообщение = Новый СообщениеПользователю();
Сообщение.Текст = «В строке 11 табличной части «»Номенклатура»» не хватает » +
НедостающееКоличество + » » + ЕдиницаИзмеренияНоменклатуры;
Сообщение.Поле = «Номенклатура.Количество»;
// Привязка объекта к реквизиту формы произойдет за счет
// установленного выше по стеку соответствия методом
// УстановитьСоответствиеОбъектаИРеквизитаФормы
Сообщение.УстановитьДанные(ОбъектДанных);
// Теперь у сообщения заполнено поле ПутьКДанным (установлено имя реквизита формы, до этого была пустая строка),
// и свойство КлючДанных (установлена ссылка на документ, до этого было Неопределено)
// Сообщение выводится пользователю
Сообщение.Сообщить();
// в дальнейшем сообщение будет показано в форме и привязано к
// элементу управления связанного с полем Количество
// в 11-й строке табличной части Номенклатура.
КонецПроцедуры;

В этом фрагменте создается новый объект СообщениеПользователю, в котором запоминается Текст сообщения и указывается Поле объекта, ошибка в данных которого вызвала необходимость вывода сообщения. Информация о том, как объект расположен в форме берется из предварительно запомненной пары «Объект/ИмяРеквизитаФормы». В дальнейшем сообщение будет выведено в окно сообщений формы и привязано к соответствующему элементу управления.

Примеры заполнения свойства Поле объекта СообщениеПользователю

ТипШаблонПример
Реквизит ИмяРеквизита Контрагент
Табличная часть ИмяТабличнойЧасти Скидки
Реквизит табличной части ИмяТабличнойЧасти.ИмяРеквизита Номенклатура.Количество
Реквизит набора записей .ИмяРеквизита .Курс

Еще примеры:

Код 1C v 8.3 &НаКлиенте
Процедура ДействиеСОбъектомНаКлиенте(ОбъектДанных)
// Какие либо действия, которые требуют создания сообщения
// Создание сообщения

Сообщение = Новый СообщениеПользователю();
Сообщение.Текст = «В строке 11 табличной части «»Номенклатура»» не хватает » +
НедостающееКоличество + » » + ЕдиницаИзмеренияНоменклатуры;
Сообщение.Поле = «Номенклатура.Количество»;
// Привязка объекта к реквизиту формы «вручную»
Сообщение.КлючДанных = ОбъектДанных.Ссылка;
Сообщение.ПутьКДанным = «Объект»;
// Сообщение выводится пользователю
Сообщение.Сообщить();
КонецПроцедуры;
&НаСервере
Процедура Сообщить4НаСервере()
Сообщение4 = новый СообщениеПользователю;
Сообщение4.УстановитьДанные(РеквизитФормыВЗначение(«Объект»));
Сообщение4.Текст = «4. Сообщение привязанное к реквизиту шапки Организация»;
Сообщение4.Поле = «Организация»;
Сообщение4.Сообщить();
КонецПроцедуры
// Показываем сообщение из обработки
// КлючДанных и ПутьКДанным — пустые
Сообщение = Новый СообщениеПользователю;
Сообщение.Поле = «Комментарий»;
Сообщение.Текст = «Заполните комментарий»;
Сообщение.Сообщить();
// Показываем сообщение из документа
// КлючДанных — пустой, ПутьКДанным заполнится автоматически
Сообщение = Новый СообщениеПользователю;
Сообщение.Поле = «Товары.Количество»;
Сообщение.Текст = «Не заполнено количество товара в первой строке!»;
Сообщение.УстановитьДанные(ЭтотОбъект);
Сообщение.Сообщить();
//////////////////// КОД для ТИПОВЫХ конфигураций, БСП:
//в модуле объекта
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(«Текст ошибки”,
ЭтотОбъект,
«Договор»,,
Отказ);
//в форме объекта
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(НСтр(«ru = ‘Дублирование пременной'»), ,
«Запросы.ИмяПеременнойЗапроса»,//путь к данным
«Объект», Отказ);

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

Код 1C v 8.3 ПоказатьОповещениеПользователя(НСтр(«ru = ‘Выполнение:'»), ПолучитьНавигационнуюСсылку(Объект), «Выгрузка завершена, все ОК!», БиблиотекаКартинок.ПолнотекстовыйПоискДалее); Код 1C v 8.3 &НаКлиенте
Процедура ПриОткрытии(Отказ)
Если ПолучитьДатуЗапретаРедактирования() >= Объект.Дата Тогда
НавигационнаяСсылка = ПолучитьНавигационнуюСсылку(Объект.Ссылка);
ПоказатьОповещениеПользователя(«Только просмотр!»,
НавигационнаяСсылка,
«Разрешен только просмотр документа!»);

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *