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