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