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