Почему при интерактивном добавлении отбора компоновки данных на управляемой форме список полей пуст и как это исправить?

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

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

В чем кроется техническая суть проблемы?

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

Когда мы инициализируем компоновщик настроек напрямую объектом схемы на сервере с помощью конструкции вида:


ИсточникДанных = Новый ИсточникДоступныхНастроекКомпоновкиДанных(МакетСхемы);
КомпоновщикНастроек.Инициализировать(ИсточникДанных);

происходит следующее:

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

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

Пошаговое решение: инициализация через временное хранилище

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

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


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

    // 1. Получаем макет схемы компоновки данных (например, из макета обработки)
    МакетСхемы = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
    
    // 2. Помещаем макет схемы во временное хранилище с обязательной привязкой к УИД формы
    АдресСхемыВоВременномХранилище = ПоместитьВоВременноеХранилище(МакетСхемы, УникальныйИдентификатор);
    
    // 3. Создаем источник доступных настроек на основании адреса хранилища
    ИсточникДанных = Новый ИсточникДоступныхНастроекКомпоновкиДанных(АдресСхемыВоВременномХранилище);
    
    // 4. Инициализируем компоновщик настроек формы полученным источником
    КомпоновщикНастроек.Инициализировать(ИсточникДанных);
    
    // 5. Загружаем дефолтные настройки из схемы компоновки
    КомпоновщикНастроек.ЗагрузитьНастройки(МакетСхемы.НастройкиПоУмолчанию);

КонецПроцедуры

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

Управление жизненным циклом данных в хранилище (Важность УИД)

Обратим особое внимание на второй параметр функции ПоместитьВоВременноеХранилище(). В примере выше мы передали туда УникальныйИдентификатор текущей управляемой формы. Это критически важный нюанс:

Альтернативный способ инициализации (через навигационную ссылку)

Посмотрим на альтернативный сценарий. Что делать, если схема компоновки данных хранится непосредственно в базе данных? Например, в реквизите справочника или документа с типом ХранилищеЗначения (актуально для механизмов дополнительных отчетов и обработок).

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


&НаСервере
Процедура ИнициализироватьКомпоновщикИзБазы(СсылкаНаНастройку)

    // Получаем навигационную ссылку на реквизит "ХранилищеНастроек", где лежит схема СКД
    АдресСхемы = ПолучитьНавигационнуюСсылку(СсылкаНаНастройку, "ХранилищеНастроек");
    
    // Инициализируем источник через навигационную ссылку
    ИсточникДанных = Новый ИсточникДоступныхНастроекКомпоновкиДанных(АдресСхемы);
    КомпоновщикНастроек.Инициализировать(ИсточникДанных);

КонецПроцедуры

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

Соблюдение строгого порядка вызова методов

При работе с компоновщиком настроек на управляемой форме критически важно соблюдать правильную последовательность действий. Запомните следующее правило построения алгоритма:

  1. Помещение схемы в хранилище (или получение навигационной ссылки).
  2. Инициализация компоновщика настроек источником доступных настроек (метод Инициализировать()).
  3. Загрузка настроек (метод ЗагрузитьНастройки()).

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

Особенности работы с пользовательскими настройками

На практике разработчики часто выводят на форму не весь основной отбор компоновщика (КомпоновщикНастроек.Настройки.Отбор), а коллекцию быстрых настроек, доступных пользователю непосредственно на форме (КомпоновщикНастроек.ПользовательскиеНастройки).

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

Чтобы программно добавить элемент отбора так, чтобы пользователь увидел его в таблице пользовательских настроек на форме, примените следующий шаблон:


// 1. Добавляем новый элемент в основные настройки компоновщика
НовыйЭлемент = КомпоновщикНастроек.Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
НовыйЭлемент.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Контрагент");
НовыйЭлемент.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
НовыйЭлемент.Использование = Истина;

// 2. Генерируем уникальный идентификатор пользовательской настройки
НовыйЭлемент.ИдентификаторПользовательскойНастройки = Строка(Новый УникальныйИдентификатор);

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

← На главную