Как обновить данные в открытой форме элемента справочника после закрытия вспомогательной формы?

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

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

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

Почему данные не обновляются автоматически

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

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

Вариант 1. Передача измененных данных через механизм оповещений без промежуточной записи

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

Рассмотрим по шагам реализацию этого механизма:

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

Посмотрим на пример кода во второй (вспомогательной) форме:


&НаКлиенте
Процедура ЗавершитьРедактирование(Команда)
    // Формируем измененные данные
    Оповестить("ОбновитьДанныеHTML", ВведенныйТекстHTML);
    ЭтаФорма.Закрыть();
КонецПроцедуры

В модуле первой (основной) формы настраиваем обработчик события ОбработкаОповещения:


&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
    Если ИмяСобытия = "ОбновитьДанныеHTML" Тогда
        Объект.ПолеHTMLДоступы = Параметр;
        ЭтаФорма.Модифицированность = Истина;
    КонецЕсли;
КонецПроцедуры

Вариант 2. Использование немодального открытия с описанием оповещения

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

Разберем алгоритм вызова формы:


&НаКлиенте
Процедура ОткрытьРедактор(Команда)
    Оповещение = Новый ОписаниеОповещения("ПослеЗакрытияРедактора", ЭтотОбъект);
    
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("ТекущийТекст", Объект.ПолеHTMLДоступы);
    
    ОткрытьФорму("Обработка.РедакторHTML.Форма.Форма", ПараметрыФормы, ЭтотОбъект,,,, Оповещение);
КонецПроцедуры

&НаКлиенте
Процедура ПослеЗакрытияРедактора(Результат, ДополнительныеПараметры) Экспорт
    Если Результат <> Неопределено Тогда
        Объект.ПолеHTMLДоступы = Результат;
        ЭтаФорма.Модифицированность = Истина;
    КонецЕсли;
КонецПроцедуры

Во вспомогательной форме для возврата данных вызываем метод Закрыть() с передачей результата:


&НаКлиенте
Процедура СохранитьИЗакрыть(Команда)
    ЭтаФорма.Закрыть(РеквизитТекстHTML);
КонецПроцедуры

Вариант 3. Перечитывание объекта через метод Прочитать()

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

Для этого в управляемых формах применяется метод ЭтаФорма.Прочитать(). Обратите внимание на важные правила его использования:

  1. Метод вызывается у объекта ЭтаФорма, а не у реквизита Объект или контекста ЭтотОбъект.
  2. Вызов метода ЭтаФорма.Прочитать() автоматически сбрасывает несохраненные правки в первой форме и инициирует серверный обработчик ПриЧтенииНаСервере.
  3. Метод применим только к уже записанным в базу объектам (у которых заполнена ссылка).

Посмотрим на реализацию оповещения в первой форме:


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

Вынесение серверной логики в обработчик ПриЧтенииНаСервере

Если при чтении данных требуется выполнить дополнительную обработку (например, преобразовать строку в форматированный HTML-документ или вычислить зависимые визуальные реквизиты), не следует дублировать вызов процедуры ПриСозданииНаСервере. Разместим всю логику подготовки данных в стандартном событии ПриЧтенииНаСервере или вынесем ее в отдельную процедуру:


&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
    // Обработка данных при открытии формы и при вызове ЭтаФорма.Прочитать()
    ОбновитьОтображениеHTMLНаСервере(ТекущийОбъект);
КонецПроцедуры

&НаСервере
Процедура ОбновитьОтображениеHTMLНаСервере(ДанныеОбъекта)
    // Заполнение дополнительных реквизитов формы для отображения
    ПолеHTMLОтображение = ДанныеОбъекта.ПолеHTMLДоступы;
КонецПроцедуры

Таким образом, использование метода ЭтаФорма.Прочитать() гарантированно запустит серверную обработку и корректно актуализирует интерфейс без необходимости повторного открытия окна пользователем.

← На главную