Как обновить программно созданный динамический список после создания нового документа в 1С?

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

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

Анализ проблемы: почему список не обновляется?

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

Посмотрим на ключевую часть запроса:


|ГДЕ
|	зн_ПалетныйЛист.Ссылка В(&МассивПЛ)

Параметр &МассивПЛ — это массив ссылок на документы, который формируется на сервере один раз, в процедуре ПриЧтенииСозданииНаСервере. Система выполняет запрос, получает данные для этого массива и "запоминает" его. Когда мы на клиенте вызываем метод Элементы.ИмяСписка.Обновить(), платформа просто перезапрашивает данные у сервера, но использует тот же самый, старый параметр &МассивПЛ. Естественно, новый, только что созданный документ в этот массив не входит, поэтому мы его и не видим в списке.

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

Решение 1: Ручное обновление параметров запроса

Это самый прямой способ решения проблемы "в лоб". Логика проста: если параметр устарел, нужно его обновить. Для этого после закрытия формы нового документа мы должны выполнить серверный вызов, в котором заново сформируем массив ссылок и установим его как новое значение параметра для нашего динамического списка.

Рассмотрим по шагам:

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

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


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

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

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

Решение 2: Использование системного механизма `ОповеститьОбИзменении`

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

Метод ОповеститьОбИзменении() как раз для этого и предназначен. Его нужно вызывать в тот момент, когда данные в базе были изменены, то есть после записи нового документа.

Разберем по шагам:

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

Пример кода для формы создаваемого документа:


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

Что произойдет после этого? Как только новый "Палетный лист" будет записан, родительская форма с нашим динамическим списком получит это уведомление. Поскольку ее динамический список отображает документы именно этого типа, платформа автоматически инициирует его обновление. В большинстве случаев вам даже не понадобится вызывать Элементы.ИмяСписка.Обновить() вручную в родительской форме.

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

Решение 3 (Рекомендуемое): Улучшение запроса динамического списка

Сама проблема возникла из-за не самого удачного запроса, который опирался на статичный, заранее подготовленный массив ссылок. Наиболее надежным решением будет переписать запрос так, чтобы он не зависел от такого массива, а использовал для отбора связь с основным документом.

Предположим, что у документа "Палетный лист" есть реквизит ЗаданиеНаПеревозку, который ссылается на основной документ, на форме которого мы находимся.

Исходный запрос:


ВЫБРАТЬ
	...
ИЗ
	Документ.зн_ПалетныйЛист КАК зн_ПалетныйЛист
ГДЕ
	зн_ПалетныйЛист.Ссылка В(&МассивПЛ)

Улучшенный запрос:


ВЫБРАТЬ
	...
ИЗ
	Документ.зн_ПалетныйЛист КАК зн_ПалетныйЛист
ГДЕ
	зн_ПалетныйЛист.ЗаданиеНаПеревозку = &ЗаданиеНаПеревозку

При таком подходе при создании динамического списка мы устанавливаем параметр &ЗаданиеНаПеревозку, равный ссылке на текущий документ (Объект.Ссылка). Этот параметр не меняется. Теперь, когда мы создаем новый "Палетный лист" и правильно заполняем в нем реквизит ЗаданиеНаПеревозку, он автоматически начинает удовлетворять условию запроса нашего списка.

Преимущества этого подхода:

После такого изменения запроса будет достаточно использовать Решение 2 (ОповеститьОбИзменении), и все будет работать идеально. Система получит уведомление, перечитает данные динамического списка по неизменному запросу и "увидит" новый документ, так как он теперь соответствует условию отбора.

← На главную