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