Почему не отображается динамический список в расширении и как это исправить

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

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

Выясним причину: почему пропадает динамический список

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

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

Способ 1. Корректное интерактивное заимствование метаданных

Если стоит задача модифицировать форму визуально непосредственно в редаторе расширения, разберем по шагам алгоритм восстановления элементов:

  1. Заимствуем контекст метаданных. Прежде чем переносить форму, убедимся, что сам объект-владелец формы (например, документ или справочник) добавлен в расширение. Также необходимо добавить все объекты метаданных, фигурирующие в тексте запроса динамического списка в секциях соединений.
  2. Добавляем реквизиты списка в расширение. Перейдем на вкладку «Реквизиты» формы расширения. Развернем реквизит динамического списка. Выделим реквизит динамического списка или его недоступные серые поля, нажмем правую кнопку мыши и выберем команду Добавить в расширение. Платформа подтянет недостающие связи, после чего структура списка станет доступной.
  3. Восстанавливаем свойство привязки данных. Перейдем в дерево элементов формы. Выделим элемент таблицы динамического списка, откроем окно его свойств и проверим свойство ПутьКДанным. Если оно пустое, вручную выберем имя реквизита динамического списка (например, Список). Аналогичную проверку выполним для дочерних колонок таблицы.
  4. Сбрасываем кэш формы. Сохраним конфигурацию расширения комбинацией клавиш Ctrl+S, закроем окно редактирования формы и откроем его заново. Таблица со списком восстановит свое отображение на визуальной панели.

Способ 2. Программное изменение динамического списка (рекомендуемый)

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

В этом сценарии мы не заимствуем реквизит списка в расширение целиком, а заимствуем только саму форму. Модификацию выполним в обработчике ПриСозданииНаСервере с директивой &После.

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


&После("ПриСозданииНаСервере")
Процедура Расш1_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
	
	// Модифицируем текст запроса динамического списка
	ТекстЗапроса = Список.ТекстЗапроса;
	
	// Для безопасной модификации можно использовать СхемаЗапроса
	// либо простую замену текста, если запрос типовой формы известен
	Если Не СтрНайти(ТекстЗапроса, "НовыйРеквизит") > 0 Тогда
		Список.ТекстЗапроса = СтрЗаменить(
			ТекстЗапроса, 
			"ВЫБРАТЬ", 
			"ВЫБРАТЬ Док.НовыйРеквизит КАК НовыйРеквизит,"
		);
	КонецЕсли;
	
	// Программно добавляем колонку в таблицу формы
	ИмяЭлемента = "СписокНовыйРеквизит";
	Если Элементы.Найти(ИмяЭлемента) = Неопределено Тогда
		НоваяКолонка = Элементы.Добавить(ИмяЭлемента, Тип("ПолеФормы"), Элементы.Список);
		НоваяКолонка.Вид = ВидПоляФормы.ПолеНадписи;
		НоваяКолонка.ПутьКДанным = "Список.НовыйРеквизит";
		НоваяКолонка.Заголовок = "Дополнительный реквизит";
	КонецЕсли;
	
КонецПроцедуры

Способ 3. Вывод данных через обработчик ПриПолученииДанныхНаСервере

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

  1. В расширении заимствуем форму и добавляем в таблицу Список новую колонку без привязки к реквизиту данных, либо создаем ее программно.
  2. Подключаем обработчик события ПриПолученииДанныхНаСервере для элемента таблицы.
  3. В обработчике считываем порцию ссылок из параметра СтрокиОформления и заполняем ячейки нужными значениями за один запрос.

Посмотрим на пример реализации данного подхода:


&НаСервере
Процедура Расш1_СписокПриПолученииДанныхНаСервере(Элемент, ОформленияСтрок)
	
	// Собираем массив ссылок текущей страницы динамического списка
	МассивСсылок = Новый Массив;
	Для Каждого СтрокаОформления Из ОформленияСтрок Цикл
		МассивСсылок.Добавить(СтрокаОформления.ДанныеСтроки.Ссылка);
	КонецЦикла;
	
	Если МассивСсылок.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;
	
	// Получаем значения пакетно
	Запрос = Новый Запрос;
	Запрос.Текст = 
		"ВЫБРАТЬ
		|	Таблица.Ссылка КАК Ссылка,
		|	Таблица.Комментарий КАК ЗначениеКолонки
		|ИЗ
		|	Документ.РеализацияТоваровУслуг КАК Таблица
		|ГДЕ
		|	Таблица.Ссылка В(&МассивСсылок)";
	Запрос.УстановитьПараметр("МассивСсылок", МассивСсылок);
	
	Выборка = Запрос.Выполнить().Выбрать();
	СоответствиеЗначений = Новый Соответствие;
	Пока Выборка.Следующий() Цикл
		СоответствиеЗначений.Вставить(Выборка.Ссылка, Выборка.ЗначениеКолонки);
	КонецЦикла;
	
	// Заполняем ячейки сформированными данными
	Для Каждого СтрокаОформления Из ОформленияСтрок Цикл
		Значение = СоответствиеЗначений[СтрокаОформления.ДанныеСтроки.Ссылка];
		Если Значение <> Неопределено Тогда
			Ячейка = СтрокаОформления.Ячейки.Найти("СписокДополнительнаяКолонка");
			Если Ячейка <> Неопределено Тогда
				Ячейка.УстановитьТекст(Строка(Значение));
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;
	
КонецПроцедуры

Таким образом, при исчезновении динамического списка в расширении следует либо последовательно заимствовать все связанные метаданные и восстановить ПутьКДанным, либо отказаться от интерактивного изменения списка в пользу программного добавления колонок и модификации запроса через серверные методы.

← На главную