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

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

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

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

Анализ ошибки: почему передача динамического списка через параметр процедуры не работает

Посмотрим на типичный ошибочный код, с которым сталкиваются разработчики:


&НаКлиенте
Процедура ОтборПоСтатусамПриИзменении(Элемент)
    СменитьЗапрос(Список, стрЗапроса);
    ЭтаФорма.ОбновитьОтображениеДанных();
    Элементы.Список.Обновить();
КонецПроцедуры

&НаСервере
Процедура СменитьЗапрос(ДС, СтрокаЗапроса)
    ДС.ТекстЗапроса = СтрокаЗапроса;
    Элементы.Список.Обновить(); // Ошибка контекста
КонецПроцедуры

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

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

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

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

Разберем правильную реализацию по шагам:


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

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

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

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

Проанализируем методы обновления, которые часто путают между собой:

  1. Метод Элементы.ИмяТаблицы.Обновить() — вызывается строго в контексте &НаКлиенте. Он инициирует повторный запрос к базе данных, перечитывает порцию данных в соответствии с текущими настройками и отображает обновленный результат пользователю.
  2. Метод ЭтаФорма.ОбновитьОтображениеДанных() — выполняет перерисовку связанных элементов формы и пересчет видимости/доступности. Этот метод не перечитывает данные из базы и не перезапускает динамический список. Использовать его для обновления списка бесполезно.

Важные последствия изменения текста запроса (СКД и основная таблица)

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

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

Альтернативные и более надежные способы управления данными списка

Изменение текста запроса «на лету» — крайняя мера, чреватая ошибками. В типовых конфигурациях применяются более гибкие и безопасные методики.

Вариант 1. Установка параметров запроса

Если структура выборки одинакова, а меняются только условия, предпочтительно заранее написать в запросе параметры и управлять ими на сервере:


&НаСервере
Процедура УстановитьФильтрПоСтатусуНаСервере(ВыбранныйСтатус)
    Список.Параметры.УстановитьЗначениеПараметра("Статус", ВыбранныйСтатус);
    Список.Параметры.УстановитьЗначениеПараметра("ФильтроватьПоСтатусу", ЗначениеЗаполнено(ВыбранныйСтатус));
КонецПроцедуры

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

Для необязательных условий используйте синтаксис фигурных скобок {ГДЕ ...}. В этом случае условие попадает в результирующий SQL-запрос только тогда, когда активен соответствующий отбор, без ручной склейки строк:


ВЫБРАТЬ
    Док.Ссылка,
    Док.Номер,
    Док.Дата,
    Док.Статус
ИЗ
    Документ.ЗаказКлиента КАК Док
{ГДЕ
    Док.Статус = &Статус}

Вариант 3. Программное управление отборами

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

← На главную