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