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

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

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

Почему возникает ошибка при передаче формы

Разберем причину этого поведения платформы. Когда мы вызываем серверную процедуру непосредственно из модуля формы, используя директиву &НаСервере, платформа выполняет автоматическую синхронизацию контекста. Объект ЭтотОбъект (сама форма) не передается по сети в явном виде; вместо этого передаются только измененные данные, а на сервере форма восстанавливается магией платформы.

Однако, как только мы пытаемся передать форму как параметр в процедуру общего модуля, эта «магия» перестает работать. Общий модуль рассматривает форму просто как объект данных. Поскольку тип УправляемаяФорма не является сериализуемым (его нельзя превратить в поток байтов и передать с клиента на сервер через сетевой протокол), платформа выдает ошибку. Выясним, как обойти это ограничение, сохранив чистоту архитектуры.

Решение 1. Создание процедур-мостов в модуле формы

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

В модуле формы (например, документа или справочника) мы прописываем минимальный код:


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

&НаСервере
Процедура ВыполнитьДействиеНаСервере(ДополнительныеПараметры) Экспорт
    // Здесь ЭтотОбъект — это серверный контекст формы.
    // Мы передаем его дальше в серверный общий модуль.
    ОбщийМодульСервер.ОбработатьДанныеФормы(ЭтотОбъект, ДополнительныеПараметры);
КонецПроцедуры

В клиентском общем модуле ОбщийМодульКлиент мы можем выполнить проверку условий и, если нужно, инициировать серверный вызов:


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

Важный момент: Процедура ВыполнитьДействиеНаСервере в модуле формы должна быть помечена словом Экспорт, иначе клиентский общий модуль её не «увидит».

Решение 2. Передача структуры данных вместо объекта формы

Если серверному общему модулю не нужно управлять элементами интерфейса (видимостью кнопок, цветом полей), а требуются только данные, мы можем передать реквизит Объект. Рассмотрим ситуацию: тип ДанныеФормыСтруктура, которым является реквизит Объект (или любая табличная часть), прекрасно сериализуется и передается на сервер.

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


Процедура ОбработатьНажатиеКнопки(Форма) Экспорт
    // Передаем не саму форму, а только данные (Объект)
    ОбщийМодульСервер.РассчитатьСуммы(Форма.Объект);
КонецПроцедуры

На стороне сервера в общем модуле:


Процедура РассчитатьСуммы(ДанныеОбъекта) Экспорт
    // Здесь ДанныеОбъекта имеют тип ДанныеФормыСтруктура.
    // Все изменения, внесенные здесь, автоматически вернутся на форму.
    ДанныеОбъекта.Сумма = ДанныеОбъекта.Количество * ДанныеОбъекта.Цена;
КонецПроцедуры

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

Решение 3. Использование универсальных структур параметров

Иногда серверу нужно знать что-то о состоянии формы, что не входит в реквизит Объект. В этом случае проанализируем подход с использованием структуры-контейнера. Мы собираем всё необходимое на клиенте и передаем одной посылкой.

  1. В клиентском общем модуле формируем структуру ПараметрыВызова.
  2. Включаем туда данные (Объект) и необходимые флаги состояния формы (например, ТолькоПросмотр или Модифицированность).
  3. Передаем структуру на сервер через «мост» в форме или напрямую в серверный модуль (если не нужен доступ к ЭтотОбъект на сервере).

Пример подготовки параметров:


ПараметрыВызова = Новый Структура;
ПараметрыВызова.Вставить("Данные", Форма.Объект);
ПараметрыВызова.Вставить("ИмяФормы", Форма.ИмяФормы);
ПараметрыВызова.Вставить("ТолькоПросмотр", Форма.ТолькоПросмотр);

// Вызываем серверный модуль
ОбщийМодульСервер.ВыполнитьОбработку(ПараметрыВызова);

Рекомендации по выбору метода

Выясним, какой метод лучше подходит под ваши задачи:

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

← На главную