Как исправить ошибку Поле объекта не обнаружено при получении реквизита ссылки на клиенте

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

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

Причина возникновения ошибки в управляемом приложении

Выясним причину такого поведения платформы. В управляемом интерфейсе действует строгое разделение логики на клиентскую (директива &НаКлиенте) и серверную (директивы &НаСервере или &НаСервереБезКонтекста).

Когда мы получаем значение ссылочного типа в клиентской процедуре (например, СправочникСсылка.Номенклатура), платформа передает его в виде легковесного ссылочного объекта. На клиенте у ссылки нет доступа к данным базы и свойствам самого объекта. Разрешены только базовые операции, такие как проверка на пустоту методом Пустая() или сравнение. Попытка обратиться к реквизиту объекта через точку (например, СтрТабЧасти.НаименованиеТовара.Товар) не вызывает автоматического запроса к серверу и СУБД, а немедленно порождает исключение платформы «Поле объекта не обнаружено».

Базовое решение: получение значения через серверную функцию

Разберем классический способ решения этой проблемы. Чтобы прочитать реквизит связанного объекта, нам необходимо отправить ссылку на сервер и вернуть полученное значение обратно на клиент.

Рассмотрим пример правильной структуры обработчика:


&НаКлиенте
Процедура ТоварНаименованиеТовараПриИзменении(Элемент)
    СтрТабЧасти = Элементы.Товар.ТекущиеДанные;
    Если СтрТабЧасти = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    СтрТабЧасти.Товар = ПолучитьТоварНаСервере(СтрТабЧасти.НаименованиеТовара);
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьТоварНаСервере(НаименованиеТовара)
    Если Не ЗначениеЗаполнено(НаименованиеТовара) Тогда
        Возврат Справочники.Номенклатура.ПустаяСсылка();
    КонецЕсли;
    
    Возврат НаименованиеТовара.Товар;
КонецФункции

Обратите внимание: мы используем директиву &НаСервереБезКонтекста. Это позволяет избежать передачи всего контекста формы на сервер и обратно, что значительно экономит трафик и ускоряет работу интерфейса.

Оптимизация и правила надежного кода

Рассмотрим по шагам правила написания безопасного и быстрого кода при работе с табличными частями на форме:

  1. Проверка наличия текущей строки. Свойство ТекущиеДанные у элемента таблицы может вернуть Неопределено (например, если фокус потерян или таблица пуста). Всегда выполняем предварительную проверку перед обращением к строке.
  2. Проверка на заполненность значения. Если пользователь очистил поле ввода, нет необходимости выполнять серверный вызов. Очистку зависимых колонок можно выполнить сразу на клиенте.
  3. Использование функций Библиотеки стандартных подсистем (БСП). Прямое обращение через точку на сервере (НаименованиеТовара.Товар) считывает объект базы данных целиком. Если в конфигурации используется БСП, намного эффективнее применить метод ОбщегоНазначения.ЗначениеРеквизитаОбъекта. Он выполняет быстрый точечный SQL-запрос только к нужной колонке.

Посмотрим на пример кода с учетом всех рекомендаций:


&НаКлиенте
Процедура ТоварНаименованиеТовараПриИзменении(Элемент)
    СтрТабЧасти = Элементы.Товар.ТекущиеДанные;
    Если СтрТабЧасти = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    Если ЗначениеЗаполнено(СтрТабЧасти.НаименованиеТовара) Тогда
        СтрТабЧасти.Товар = ПолучитьЗначениеТовара(СтрТабЧасти.НаименованиеТовара);
    Иначе
        СтрТабЧасти.Товар = Неопределено;
    КонецЕсли;
КонецПроцедуры

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

Альтернативный вариант: получение нескольких реквизитов

Проанализируем случай, когда при выборе одного элемента необходимо заполнить сразу несколько колонок строки (например, Товар, ЕдиницаИзмерения, СтавкаНДС). Чтобы не делать отдельный серверный вызов для каждого поля, передаем и возвращаем структуру данных.

Рассмотрим реализацию:


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

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

Такой подход минимизирует количество клиент-серверных вызовов и обеспечивает высокую отзывчивость интерфейса при редактировании документов.

← На главную