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