В процессе разработки на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с необходимостью динамического изменения интерфейса. Одной из типичных задач является программный вывод реквизита, который уже определен в метаданных (в основной конфигурации или расширении), на управляемую форму. Однако здесь часто возникает путаница между понятиями "Реквизит формы" и "Элемент формы". Проанализируем типичную ситуацию и разберем правильный алгоритм действий.
Рассмотрим ситуацию, когда в основной конфигурации уже создан реквизит, например, Преф_АдресДоставки. Разработчик пытается добавить его на форму через расширение, используя метод ИзменитьРеквизиты. В ответ платформа выдает ошибку: "Недопустимый путь к реквизиту". Выясним, почему это происходит.
Основная причина кроется в непонимании принципов работы Управляемых Форм (УФ):
Объект.ИмяРеквизита.ИзменитьРеквизиты служит исключительно для создания новых временных путей в памяти.Попытка вызвать ИзменитьРеквизиты для уже существующего поля объекта — это попытка создать дубликат в памяти формы с тем же именем, что и приводит к конфликту и ошибке пути. Как правильно заметили участники обсуждения, если реквизит уже есть в объекте, его не нужно "создавать" в данных формы — он там уже присутствует.
Чтобы вывести уже существующий в метаданных реквизит на форму, нам не нужно менять состав данных формы. Нам нужно создать только визуальный Элемент формы (виджет) и связать его с уже имеющимися данными. Рассмотрим этот процесс по шагам.
Проанализируем пример кода, который необходимо разместить в процедуре ПриСозданииНаСервере (или в соответствующем после-обработчике расширения):
// 1. Определяем имя нового элемента и его тип (ПолеФормы)
ИмяЭлемента = "Преф_АдресДоставки";
ТипПоля = Тип("ПолеФормы");
// 2. Добавляем элемент на форму.
// Третий параметр - родитель (например, группа формы или сама форма)
НовыйЭлемент = Элементы.Добавить(ИмяЭлемента, ТипПоля, ЭтаФорма);
// 3. Указываем путь к существующим данным объекта
НовыйЭлемент.ПутьКДанным = "Объект.Преф_АдресДоставки";
// 4. Обязательно устанавливаем вид поля, иначе оно может не отобразиться корректно
НовыйЭлемент.Вид = ВидПоляФормы.ПолеВвода;
// 5. Опционально настраиваем заголовок и другие свойства
НовыйЭлемент.Заголовок = "Адрес доставки (добавлен программно)";
В данном случае платформа понимает, что Объект.Преф_АдресДоставки — это легальный путь к данным, которые уже загружены в форму вместе с основным объектом. Данные будут автоматически сохраняться при записи документа, так как они напрямую связаны с реквизитом базы данных.
Рассмотрим важный нюанс, касающийся расширений. Многие задаются вопросом: нужно ли заимствовать реквизит в расширение для программного обращения к нему? С технической точки зрения, для работы свойства ПутьКДанным в коде заимствование не является строго обязательным, так как это просто строка. Однако проанализируем последствия отсутствия заимствования:
Разберем ситуации, в которых использование ИзменитьРеквизиты является оправданным и необходимым. Этот метод предназначен для динамических свойств, которые не хранятся в объекте метаданных. Посмотрим на примеры:
Рассмотрим пример правильного создания динамического реквизита формы, который не связан с объектом:
ДобавляемыеРеквизиты = Новый Массив;
// Создаем реквизит "ТолькоДляФормы", он не существует в метаданных документа
ДобавляемыеРеквизиты.Добавить(Новый РеквизитФормы("ТолькоДляФормы", Новый ОписаниеТипов("Булево"), , "Флаг отображения", Истина));
// Применяем изменения к структуре формы
ИзменитьРеквизиты(ДобавляемыеРеквизиты);
// Теперь можем создать элемент и связать его с новым реквизитом
ЭлементФлаг = Элементы.Добавить("ПолеФлаг", Тип("ПолеФормы"), ЭтаФорма);
ЭлементФлаг.ПутьКДанным = "ТолькоДляФормы";
ЭлементФлаг.Вид = ВидПоляФормы.ПолеФлажка;
Важно помнить, что метод ИзменитьРеквизиты — это "тяжелая" операция для платформы 1С. Посмотрим, что происходит в момент его вызова:
Поэтому рекомендуется собирать все изменения (добавление и удаление нескольких реквизитов) в один массив и вызывать ИзменитьРеквизиты один раз в рамках одной серверной процедуры. Также стоит учитывать, что вы не можете программно удалить реквизиты, которые были добавлены статически в конфигураторе — метод работает только с теми данными, которые были созданы программно.
Что касается Табличных Частей, о которых упоминал автор темы: если вы добавляете новую ТЧ, которой нет в объекте, вы используете ИзменитьРеквизиты для создания типа ДанныеФормыКоллекция. Но если ТЧ уже существует в метаданных, подход должен быть таким же, как с обычным полем: добавляем элемент формы типа ТаблицаФормы и связываем его с Объект.ИмяВашейТЧ.
Подводя итог, всегда проверяйте, существует ли поле в метаданных объекта. Если да — просто добавляйте Элемент. Если нет — сначала создавайте РеквизитФормы через ИзменитьРеквизиты, а затем визуальный Элемент.