Как реализовать редактирование реквизитов связанного справочника прямо в форме основного объекта

Программист 1С v8.3 (Управляемые формы) Торговля и дистрибуция
← На главную

При разработке интерфейсов в среде 1С:Предприятие 8.3 часто возникает задача повышения эргономики работы пользователя. Одной из таких задач является редактирование данных связанного объекта (например, справочника «Модели») непосредственно в карточке владельца (например, справочника «Автомобили»). По умолчанию платформа позволяет выводить данные связанных объектов через «путь к данным» (Объект.Модель.Наименование), но такие поля доступны только для чтения. В этой статье мы подробно разберем, как обойти это ограничение и реализовать полноценное редактирование.

В чем заключается основная проблема?

Когда мы указываем в пути к данным элемента формы путь через точку (например, Объект.СсылкаНаСправочник.НужныйРеквизит), система обращается к данным через ссылку. Ссылочные данные в управляемых формах защищены от прямого изменения для обеспечения целостности данных. Чтобы редактировать объект, нам необходимо получить его в память сервера как СправочникОбъект, изменить его и вызвать метод Записать(). Мы рассмотрим наиболее эффективный способ реализации этого механизма через реквизиты формы.

Шаг 1. Создание реквизита формы для хранения объекта

Для начала проанализируем ситуацию: нам нужно иметь доступ к данным другого справочника в контексте текущей формы. Создавать 20-30 отдельных реквизитов для каждого поля «Модели» нецелесообразно. Правильным подходом будет создание одного реквизита формы, который будет содержать весь объект целиком.

  1. Откроем редактор формы основного справочника (например, «Автомобили»).
  2. Перейдем на закладку «Реквизиты».
  3. Добавим новый реквизит формы (не путать с реквизитом объекта!). Назовем его, например, ДанныеМодели.
  4. В поле «Тип» выберем СправочникОбъект.Модели (вместо привычной ссылки).

Важный момент: Реквизиты формы с типом СправочникОбъект позволяют напрямую связывать свои поля с элементами формы (полями ввода), и эти поля будут доступны для редактирования.

Шаг 2. Заполнение данных при открытии формы

Теперь выясним, как «пробросить» данные из существующей ссылки в наш новый реквизит формы. Для этого используются методы платформы ЗначениеВРеквизитФормы и РеквизитФормыВЗначение. Разберем программный код, который необходимо разместить в модуле формы.

Нам понадобится серверная процедура, вызываемая при создании или чтении данных:


&НаСервере
Процедура ЗаполнитьДанныеСвязанногоСправочникаНаСервере()
    
    // Проверяем, заполнена ли ссылка на модель в основном объекте
    Если ЗначениеЗаполнено(Объект.Модель) Тогда
        
        // Получаем объект справочника по ссылке
        ОбъектМодели = Объект.Модель.ПолучитьОбъект();
        
        // Копируем данные объекта в реквизит формы
        // "ДанныеМодели" — это имя нашего реквизита формы с типом СправочникОбъект
        ЗначениеВРеквизитФормы(ОбъектМодели, "ДанныеМодели");
        
    КонецЕсли;
    
КонецПроцедуры

Эту процедуру следует вызывать в стандартных обработчиках ПриСозданииНаСервере или ПриЧтенииНаСервере, чтобы при открытии карточки пользователя поля сразу заполнялись актуальными данными.

Шаг 3. Сохранение изменений в связанном справочнике

Просто изменить данные на форме недостаточно — их нужно записать в базу данных. Проанализируем, где это лучше сделать. Оптимальным местом является обработчик ПередЗаписьюНаСервере основной формы. Это гарантирует, что и автомобиль, и его модель будут сохранены (или отклонены) в рамках одной транзакции.


&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
    
    // Преобразуем данные из реквизита формы обратно в объект прикладного решения
    ОбъектМоделиДляЗаписи = РеквизитФормыВЗначение("ДанныеМодели", Тип("СправочникОбъект.Модели"));
    
    Попытка
        // Записываем изменения в справочник моделей
        ОбъектМоделиДляЗаписи.Записать();
    Исключение
        // Если возникла ошибка (например, нарушение прав или блокировка), отменяем запись основного объекта
        Сообщение = Новый СообщениеПользователю;
        Сообщение.Текст = "Не удалось сохранить данные модели: " + КраткоеОписаниеОшибки(ИнформацияОбОшибке());
        Сообщение.Сообщить();
        Отказ = Истина;
    КонецПопытки;
    
КонецПроцедуры

Шаг 4. Обработка изменения ссылки

Рассмотрим ситуацию: пользователь решил выбрать в карточке автомобиля другую модель. В этот момент данные в наших дополнительных полях станут неактуальными, так как они все еще хранят информацию о «старой» модели. Нам необходимо реализовать обновление. Для этого создадим обработчик события ПриИзменении для поля Объект.Модель.


&НаКлиенте
Процедура МодельПриИзменении(Элемент)
    // Вызываем серверную процедуру для обновления данных формы
    ОбновитьДанныеМоделиНаСервере();
КонецПроцедуры

&НаСервере
Процедура ОбновитьДанныеМоделиНаСервере()
    // Повторяем логику заполнения реквизита формы из Шага 2
    Если ЗначениеЗаполнено(Объект.Модель) Тогда
        ЗначениеВРеквизитФормы(Объект.Модель.ПолучитьОбъект(), "ДанныеМодели");
    Иначе
        // Если модель очищена, очищаем и реквизит формы
        // Создаем пустой объект нужного типа
        ПустойОбъект = Справочники.Модели.СоздатьЭлемент();
        ЗначениеВРеквизитФормы(ПустойОбъект, "ДанныеМодели");
    КонецЕсли;
КонецПроцедуры

Важные предостережения и архитектурные нюансы

Реализуя подобный механизм, мы должны помнить о нескольких критически важных моментах, которые могут повлиять на стабильность системы:

  1. Глобальное изменение данных: Справочник «Модели» обычно является общим классификатором. Если пользователь изменит, например, «Тип кузова» в карточке одного автомобиля, это изменение отразится во всех автомобилях этой модели. Нужно убедиться, что пользователь осознает это влияние. Рекомендуется визуально выделять такие поля на форме (например, рамкой или другим цветом фона), чтобы отделить их от индивидуальных характеристик конкретной машины.
  2. Блокировки объектов: Когда форма автомобиля открыта и данные модели загружены в СправочникОбъект, при записи происходит блокировка записи модели. Если два пользователя одновременно редактируют разные автомобили одной и той же модели, один из них может получить ошибку блокировки при попытке записи.
  3. Права доступа: У пользователя должны быть права не только на изменение «Автомобилей», но и на изменение «Моделей». Если прав на запись моделей нет, метод Записать() вызовет исключение.
  4. Производительность: Если в справочнике «Модели» сотни реквизитов, загрузка всего объекта целиком может быть избыточной. В таких случаях лучше использовать структуру или отдельные реквизиты формы для 5-10 наиболее часто используемых полей, заполняя их простым запросом ПриСозданииНаСервере.

Использование реквизита формы с типом СправочникОбъект — это мощный и относительно простой способ создания сложных интерфейсов «всё в одном». Мы рассмотрели полный цикл: от создания реквизита до обработки транзакционной записи. Применяйте этот метод осторожно, учитывая бизнес-логику вашего приложения.

← На главную