Как правильно реализовать обработку выбора в управляемых формах 1С 8.3

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

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

Разбор типичной ошибки: почему событие ОбработкаВыбора не срабатывает

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

Рассмотрим пример некорректного кода:


// ОШИБОЧНЫЙ ПОДХОД
&НаКлиенте
Процедура ЗаполнитьМаршрут(Команда)
    ВыбФорма = ПолучитьФорму("Справочник.ТиповыеМаршрутыЗаявок_ЕО.Форма.ФормаВыбора"); 
    ВыбФорма.Открыть();
КонецПроцедуры

В данном случае форма открыта «в никуда». Чтобы механизм заработал автоматически, необходимо явно указать Владельца формы выбора.

Решение №1: Использование метода ОткрытьФорму с указанием владельца

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

Исправим наш код, чтобы он соответствовал стандартам управляемого приложения:


&НаКлиенте
Процедура ЗаполнитьМаршрут(Команда)
    // Очищаем табличную часть перед заполнением
    Объект.ЭтапыРабот.Очистить();
    
    // Указываем владельцем саму форму (ЭтаФорма)
    // Параметры: ИмяФормы, Параметры, Владелец
    ОткрытьФорму("Справочник.ТиповыеМаршрутыЗаявок_ЕО.Форма.ФормаВыбора", , ЭтаФорма);
КонецПроцедуры

Теперь в основной форме должна быть процедура-обработчик события ОбработкаВыбора. Рассмотрим, как она должна выглядеть:


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

Решение №2: Современный подход через ОписаниеОповещения

Хотя использование владельца формы является рабочим методом, в современной разработке на платформе 8.3 (особенно в конфигурациях на базе БСП) предпочтительнее использовать механизм Описания оповещения. Это позволяет избежать нагромождения условий в общей процедуре ОбработкаВыбора и делает код более читаемым.

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


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

&НаКлиенте
Процедура ПослеВыбораМаршрута(РезультатВыбора, ДополнительныеПараметры) Экспорт
    Если РезультатВыбора <> Неопределено Тогда
        ОбработатьЗаполнениеСпискаЭтапов(РезультатВыбора);
    КонецЕсли;
КонецПроцедуры

Важно помнить: процедура, указанная в ОписаниеОповещения, обязательно должна иметь признак Экспорт.

Как получить данные выбранного объекта: Клиент vs Сервер

Частой ошибкой новичков является попытка обратиться к реквизитам выбранной ссылки прямо на клиенте. В управляемых формах объект СправочникСсылка на клиенте содержит только минимальный набор данных (например, Ссылка и Представление). Если вам нужно перебрать строки табличной части выбранного справочника или получить значения его реквизитов, необходимо перейти на сервер.

Выясним причину ошибки: если вы напишете Для Каждого ТекСтрока Из Маршрут.Этапы Цикл в процедуре с директивой &НаКлиенте, система выдаст ошибку, так как коллекция Этапы недоступна на клиенте.

Правильный алгоритм действий выглядит так:

  1. Получаем ссылку в обработчике выбора на клиенте.
  2. Передаем эту ссылку в серверную процедуру.
  3. На сервере получаем объект или данные ссылки и заполняем табличную часть формы.

Проанализируем пример реализации:


&НаКлиенте
Процедура ОбработатьЗаполнениеСпискаЭтапов(Маршрут)
    // Вызываем серверную процедуру для работы с данными объекта
    ЗаполнитьТабличнуюЧастьНаСервере(Маршрут);
КонецПроцедуры

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

Оптимизация: передача структуры данных вместо ссылки

Чтобы минимизировать количество серверных вызовов (round-trips), что критично для работы через веб-клиент или при медленном соединении, можно использовать прием передачи структуры. Если вы сами контролируете код формы выбора, вы можете подготовить все необходимые данные прямо там и передать их в ОповеститьОВыборе().

В форме выбора справочника ТиповыеМаршрутыЗаявок_ЕО напишем следующий код:


&НаКлиенте
Процедура СписокВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;
    // Подготавливаем данные на сервере, чтобы не делать лишних вызовов в основной форме
    ДанныеВыбора = ПолучитьДанныеМаршрутаНаСервере(ВыбраннаяСтрока);
    ОповеститьОВыборе(ДанныеВыбора);
КонецПроцедуры

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

Нюансы параметра «Владелец» и события «ПриИзменении»

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

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

Резюме

Для успешной реализации выбора в управляемых формах 1С 8.3:

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