При переходе с обычных форм платформы 1С:Предприятие 8.2 на управляемые формы версии 8.3 разработчики часто сталкиваются с изменением парадигмы работы с данными. В обычных формах значение поля ввода нередко считывали напрямую из визуального элемента: ЭлементыФормы.ИмяЭлемента.Значение. В управляемом интерфейсе такая конструкция вызывает ошибку, так как концепция платформы строго разделяет данные и элементы их отображения.
Разберем подробно, как устроена работа с данными в управляемых формах, как правильно читать и изменять значения реквизитов и каких типичных ошибок следует избегать.
В управляемой форме элементы диалога (поля ввода, флажки, переключатели) служат исключительно для визуализации и ввода данных. Они не хранят сами значения. Данные содержатся в реквизитах формы или реквизитах основного объекта формы (обычно это Объект).
Чтобы получить значение реквизита, не нужно обращаться к коллекции Элементы. Достаточно обратиться напрямую к реквизиту в контексте формы:
Объект.ИмяРеквизита.ИмяРеквизитаФормы.Посмотрим на пример правильного обращения к данным в коде формы:
&НаКлиенте
Процедура ПроверитьЗначение()
// Получение значения реквизита основного объекта формы
ЗначениеКаталога = Объект.НовыйКаталогФайлов;
// Получение значения собственного дополнительного реквизита формы
ФлагОтправки = РеквизитФормыОтправлятьУведомление;
КонецПроцедуры
Обратите внимание, что указание конструкции ЭтаФорма.Объект.ИмяРеквизита является синтаксически избыточным: в контексте модуля формы ключевое слово ЭтаФорма можно опускать.
При попытке получить значение разработчики иногда ошибочно используют метод ПолучитьРеквизиты(), передавая в него выражение с данными: ПолучитьРеквизиты(Объект.Реквизит). В результате возникает исключение: Недопустимое значение параметра (параметр номер '1').
Выясним причину этой ошибки. Метод ПолучитьРеквизиты() не предназначен для считывания значений из полей. Это служебный метод программного изменения состава формы, который возвращает массив описаний реквизитов (объектов метаданных типа РеквизитФормы). В качестве входного параметра он принимает строку с путем к родительскому элементу (например, пустая строка для корня формы или строка "Объект"), а не переменные с данными.
В обычных формах обращение к строке таблицы часто происходило через свойство ТекущиеДанные табличного поля. В управляемых формах табличные части и динамические списки также отображаются через элементы, и здесь механизм выглядит похожим образом, но с важными ограничениями.
Рассмотрим правила работы со свойством ТекущиеДанные:
ТекущиеДанные доступно только на клиенте через элемент формы: Элементы.ИмяТаблицы.ТекущиеДанные.Неопределено. Поэтому обязательно выполняйте проверку перед считыванием колонок.Посмотрим на пример безопасного считывания реквизита текущей строки:
&НаКлиенте
Процедура ОбработатьТекущуюСтроку()
СтрокаТаблицы = Элементы.Товары.ТекущиеДанные;
Если СтрокаТаблицы <> Неопределено Тогда
ВыбранныйТовар = СтрокаТаблицы.Номенклатура;
КоличествоТовара = СтрокаТаблицы.Количество;
КонецЕсли;
КонецПроцедуры
Если имя реквизита становится известным только во время выполнения алгоритма (например, передается в виде строки), обращаться через точку невозможно. В управляемой форме реквизит Объект имеет тип ДанныеФормыСтруктура, что позволяет использовать обращение по строковому индексу в квадратных скобках:
&НаСервере
Функция ПолучитьЗначениеДинамически(ИмяКолонки)
Возврат Объект[ИмяКолонки];
КонецФункции
Если же необходимо динамически получить собственный реквизит самой формы, используйте контекстное обращение:
ЗначениеФормы = ЭтотОбъект[ИмяРеквизитаФормы];
Иногда требуется получить значение, которое пользователь уже начал вводить в поле ввода, но еще не нажал клавишу «Enter» или не ушел с поля. В этот момент реквизит формы еще не обновлен введенным значением.
В таком случае для получения текущего отображаемого текста на стороне клиента используется специальное свойство элемента управления:
&НаКлиенте
Процедура ПолеВводаАвтоПодбор(Элемент, Текст, ДанныеВыбора, Ожидание, СтандартнаяОбработка)
ТекущийТекст = Элементы.ИмяПоляВвода.ТекстРедактирования;
КонецПроцедуры
Важно помнить, что реквизит Объект на сервере формы является не прикладным объектом базы данных (не СправочникОбъект и не ДокументОбъект), а структурой ДанныеФормыСтруктура. У него нет методов Записать(), проведения или вызова экспортных процедур модуля объекта.
Если требуется применить методы объекта базы данных, выполним преобразование через специальный механизм:
&НаСервере
Процедура ВыполнитьДействиеСОбъектом()
// Конвертируем данные формы в реальный прикладной объект
РеальныйОбъект = РеквизитФормыВЗначение("Объект");
// Вызываем методы объекта
РеальныйОбъект.ЗаполнитьПоУмолчанию();
// Возвращаем измененные данные обратно в форму
ЗначениеВРеквизитФормы(РеальныйОбъект, "Объект");
КонецПроцедуры