Реквизиты и элементы формы

Разбираемся, чем «данные формы» отличаются от «того, что видит пользователь», и почему это две разные вещи.

Реквизит формы — это ячейка данных внутри формы (число, строка, ссылка на объект). Элемент формы — это визуальный контрол (поле ввода, кнопка, таблица), через который пользователь видит и меняет реквизит.

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

Зачем это нужно на практике

В старых («обычных») формах 1С данные и интерфейс были склеены: поле на форме напрямую держало значение. В управляемых формах их специально разделили. Причина — тонкий клиент и веб-клиент: форма живёт частично на сервере (где лежат данные), частично на клиенте (где рисуется картинка в браузере). Чтобы это работало по сети, платформе нужно чётко знать, что за данные (реквизиты) она гоняет между клиентом и сервером, и как их показать (элементы).

Практический вывод: если вам в коде нужно значение — вы обращаетесь к реквизиту. Если нужно поменять внешний вид (спрятать поле, сделать его недоступным, покрасить) — вы обращаетесь к элементу.

Реквизит формы: где живут данные

Реквизит формы — это именованное хранилище значения определённого типа. У него есть имя, тип (Число, Строка, Дата, СправочникСсылка.Контрагенты и т. д.) и само значение. В коде модуля формы реквизит доступен просто по имени — как переменная.

&НаКлиенте
Процедура РассчитатьИтог()
    // Сумма и Скидка — реквизиты формы типа Число.
    // Обращаемся к ним по имени, как к обычным переменным.
    Если Скидка < 0 Тогда
        Скидка = 0;
    КонецЕсли;
    ИтогоКОплате = Сумма - Скидка;
КонецПроцедуры

Обратите внимание: Сумма, Скидка, ИтогоКОплате — это реквизиты формы. Мы читаем и пишем их напрямую, никаких «полей» тут не упоминается. Данные и только данные.

Типы реквизитов

Реквизит может быть примитивного типа (Число, Строка, Булево, Дата) или ссылочного (ссылка на элемент справочника, документ, перечисление). Отдельно бывают табличные части формы — реквизиты типа «ТаблицаЗначений» или «ДинамическийСписок», которые хранят набор строк.

&НаСервере
Процедура ЗаполнитьПоУмолчанию()
    // Реквизит "Контрагент" — тип СправочникСсылка.Контрагенты.
    // Реквизит "ДатаДокумента" — тип Дата.
    ДатаДокумента = ТекущаяДата();
    Валюта = Справочники.Валюты.НайтиПоКоду("643"); // рубль
КонецПроцедуры

Элемент формы: то, что видит пользователь

Элемент формы — это визуальный контрол. Поле ввода, флажок, кнопка, таблица, группа, декорация (надпись). У элемента есть свойства оформления и поведения: Заголовок, Видимость, Доступность, ТолькоПросмотр, ЦветТекста. Значение элемент сам не хранит — он «смотрит» в реквизит через свойство ПутьКДанным.

В коде ко всем элементам обращаются через коллекцию Элементы:

&НаКлиенте
Процедура УправлятьВидимостьюСкидки()
    // Прячем поле "Скидка" на экране, если сумма маленькая.
    // Меняем ЭЛЕМЕНТ (внешний вид), а не реквизит (значение).
    Элементы.Скидка.Видимость = (Сумма >= 1000);
    Элементы.Скидка.Доступность = НЕ ЗаказЗакрыт;
КонецПроцедуры

Здесь Элементы.Скидка — это поле ввода на форме, а не число. Число — это реквизит Скидка. По совпадению имён их легко перепутать, но это принципиально разные сущности: одно хранит значение, другое его рисует.

Основной реквизит: сердце формы

У формы объекта (документа, элемента справочника) есть особый реквизит — основной. Он совпадает с типом самого объекта: у формы документа «РасходнаяНакладная» основной реквизит обычно называется Объект и имеет тип ДокументОбъект.РасходнаяНакладная. Именно через него форма связана с данными в базе.

Основной реквизит формы — реквизит, помеченный как основной (выделен жирным в дереве реквизитов). Через него форма редактирует «настоящий» объект базы данных; при записи формы записывается именно он.

&НаКлиенте
Процедура ПриИзмененииКоличества(Элемент)
    // Обращаемся к реквизитам ЧЕРЕЗ основной реквизит "Объект".
    // Объект.Товары — табличная часть документа.
    СтрокаТовара = Элементы.Товары.ТекущиеДанные;
    Если СтрокаТовара <> Неопределено Тогда
        СтрокаТовара.Сумма = СтрокаТовара.Количество * СтрокаТовара.Цена;
    КонецЕсли;
КонецПроцедуры

Поля шапки документа на форме (Объект.Контрагент, Объект.Дата) — это элементы, чьи ПутьКДанным указывают внутрь основного реквизита. Поэтому пользователь, редактируя поле на экране, на самом деле меняет свойство объекта базы данных.

Как это работает

Под капотом связь «элемент → реквизит» задаётся свойством элемента ПутьКДанным. Например, у поля ввода «Контрагент» путь к данным равен Объект.Контрагент. Платформа при отрисовке берёт значение по этому пути и показывает его; когда пользователь вводит новое значение, платформа записывает его обратно в реквизит по тому же пути. Это двусторонняя привязка данных (data binding).

Важно, что реквизиты формы физически передаются между клиентом и сервером как единый пакет — контекст формы. Поэтому реквизиты стараются держать «лёгкими»: гнать по сети мегабайты в реквизите — плохая идея. Элементы же существуют только на клиенте (это картинка), их состояние сервер восстанавливает при каждом обращении.

Частые ошибки

  • Путать реквизит и элемент. Новичок пишет Скидка.Видимость = Ложь и получает ошибку: у числа нет свойства «Видимость». Видимость есть у элемента: Элементы.Скидка.Видимость = Ложь.
  • Думать, что элемент хранит значение. Попытка прочитать «что ввёл пользователь» через Элементы.Сумма.Значение — тупик. Значение лежит в реквизите Сумма (или Объект.Сумма), туда и смотрите.
  • Забыть основной реквизит. Данные шапки документа — это Объект.Контрагент, а не просто Контрагент. Обращение к «голому» имени, которого нет среди реквизитов формы, приводит к ошибке компиляции.
  • Класть в реквизит тяжёлые данные. Огромная ТаблицаЗначений в реквизите раздувает контекст формы и замедляет обмен клиент-сервер.

Итоги

  • Реквизит формы — это данные (значение и его тип); элемент формы — это визуальный контрол.
  • Значения читаем и пишем через реквизиты; внешний вид (видимость, доступность, заголовок) — через Элементы.ИмяЭлемента.
  • Основной реквизит (обычно Объект) связывает форму с редактируемым объектом базы; поля шапки — это Объект.Поле.
  • Связь элемента с данными задаётся свойством ПутьКДанным — это двусторонняя привязка.
Проверьте себя
1. Пользователь ввёл число в поле «Сумма» на форме. Откуда правильно прочитать это значение в коде?
AИз элемента: Элементы.Сумма.Значение
BИз реквизита: Сумма (или Объект.Сумма)
CИз свойства Элементы.Сумма.ТекущееЗначение
DЗначение нельзя прочитать программно, только показать
2. Что нужно изменить, чтобы СКРЫТЬ поле «Скидка» на экране?
AСкидка.Видимость = Ложь
BЭлементы.Скидка.Видимость = Ложь
CСкидка = Неопределено
DОбъект.Скидка.Скрыть()