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