Как оповестить одну форму о событии, произошедшем в серверной процедуре другой формы?

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

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

Проблема: Почему «Оповестить» не работает на сервере?

Метод Оповестить() является процедурой глобального контекста клиентского приложения. Когда мы находимся в серверной процедуре (например, ПриЗаписиНаСервере), контекст формы ограничен сервером, и прямое обращение к пользовательскому интерфейсу невозможно. Попытка вызвать клиентский метод из серверного кода приведет к ошибке компиляции: «Процедура или функция с указанным именем не определена». Проанализируем, как обойти это ограничение и передать сигнал между формами.

Решение 1: Использование клиентского события «ПослеЗаписи»

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

Рассмотрим по шагам реализацию в Форме_2 (форма объекта):

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

Пример кода для Формы_2:


&НаКлиенте
Процедура ПослеЗаписи(ПараметрыЗаписи)
    // Отправляем глобальное оповещение всем открытым формам
    Оповестить("СобытиеСозданияОбъекта", ПараметрыЗаписи, ЭтаФорма);
КонецПроцедуры

Теперь в Форме_1 (форма списка) нам нужно «поймать» это событие. Для этого используется стандартный обработчик ОбработкаОповещения:


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

Решение 2: Передача признака события через «ПараметрыЗаписи»

Иногда нужно отправить оповещение только в том случае, если на сервере произошло определенное «жуткое событие». Чтобы передать информацию с сервера на клиент внутри одной формы, удобно использовать структуру ПараметрыЗаписи.

Разберем этот алгоритм:

  1. В процедуре ПриЗаписиНаСервере добавляем в структуру ПараметрыЗаписи свой флаг.
  2. В процедуре ПослеЗаписи проверяем наличие этого флага.

Пример реализации на сервере:


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

Пример обработки на клиенте:


&НаКлиенте
Процедура ПослеЗаписи(ПараметрыЗаписи)
    Если ПараметрыЗаписи.Свойство("ОбъектСозданПрограммно") Тогда
        Если ПараметрыЗаписи.ОбъектСозданПрограммно Тогда
            Оповестить("ОбъектБылСоздан", ПараметрыЗаписи.СсылкаНаНовыйОбъект);
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Решение 3: Метод «ОповеститьОбИзменении»

Если ваша задача — просто обновить динамические списки во всех открытых формах, чтобы они отобразили новые данные, рассмотрите метод ОповеститьОбИзменении(). Этот метод сообщает платформе, что данные определенного типа изменились, и формы, отображающие эти данные, должны синхронизироваться.

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


&НаКлиенте
Процедура ПослеВыполненияСервернойОперации()
    ОповеститьОбИзменении(Тип("СправочникСсылка.Номенклатура"));
КонецПроцедуры

Решение 4: Автообновление динамического списка

В некоторых случаях (например, когда создание объектов происходит в фоновых заданиях или другими пользователями), прямое оповещение невозможно. Тогда в Форме_1 можно настроить период обновления динамического списка. Выясним, как это сделать:

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

Решение 5: Система взаимодействия (Collaboration System)

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

Проанализируем пример отправки сообщения с сервера:


&НаСервере
Процедура СоздатьСобытиеЧерезСистемуВзаимодействия()
    // Создаем сообщение в специальный канал или конкретному пользователю
    Сообщение = СистемаВзаимодействия.СоздатьСообщение(ИдентификаторОбсуждения);
    Сообщение.Текст = "ОбъектСоздан";
    Сообщение.Записать();
КонецПроцедуры

В форме списка (Форма_1) в обработчике ПриПолученииСообщенияСистемыВзаимодействия вы сможете мгновенно отреагировать на это событие и обновить данные.

Подведение итогов

Для стандартных задач взаимодействия между формами в рамках одного сеанса пользователя наилучшим решением является связка серверной процедуры записи и клиентского события ПослеЗаписи с вызовом Оповестить(). Это обеспечивает надежную передачу данных без лишней нагрузки на систему. Если же требуется только актуализация списков, используйте ОповеститьОбИзменении().

← На главную