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