При разработке интерфейсов на управляемых формах 1С часто возникает задача: ограничить выбор пользователя в одной колонке таблицы в зависимости от того, что введено в другой. Например, выбрав категорию товара, мы хотим видеть в соседней ячейке только те характеристики, которые относятся к этой категории. Рассмотрим, как правильно реализовать такой функционал, разберем типичные ошибки и выберем наиболее оптимальный способ взаимодействия клиента и сервера.
Представим, что у нас есть таблица значений на форме. В первой колонке Вид3CAD выбирается категория, а во второй колонке Значение нам нужно предоставить пользователю список строк или ссылок, хранящихся в справочнике и связанных с этой категорией. Типичная ошибка начинающего разработчика — попытка использовать событие НачалоВыбораИзСписка, которое на управляемых формах ведет себя иначе, чем в обычных, или вовсе не срабатывает для динамических наборов данных.
Проанализируем основные способы решения этой задачи, начиная с того, что было предложено на форуме, и заканчивая профессиональными приемами оптимизации.
Этот метод является классическим. Мы перехватываем момент, когда пользователь нажимает кнопку выбора в ячейке, и программно формируем список именно для этого конкретного элемента управления.
Разберем алгоритм действий по шагам:
НачалоВыбора.СписокВыбора элемента управления.Посмотрим на пример кода, который обсуждался в теме, но с важным дополнением. Важно помнить, что в управляемой форме элемент управления в колонке — один на всю колонку. Если мы просто будем добавлять в него значения, то при переходе от строки к строке список будет бесконечно расти и дублироваться. Поэтому обязательно нужно использовать метод Очистить().
&НаКлиенте
Процедура Таблица1ЗначениеНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
// Получаем текущие данные строки таблицы
ТекущаяСтрока = Элементы.Таблица1.ТекущиеДанные;
Если ТекущаяСтрока = Неопределено Тогда
Возврат;
КонецЕсли;
// Отменяем стандартное поведение платформы
СтандартнаяОбработка = Ложь;
// Очищаем старый список выбора, иначе значения будут дублироваться
Элемент.СписокВыбора.Очистить();
// Получаем новый список с сервера
ТЗЗнач = ЗаполнитьСписокНовыйНаСервере(ТекущаяСтрока.Вид3CAD);
// Заполняем список выбора элемента
Для Каждого ЭлементСписка Из ТЗЗнач Цикл
Элемент.СписокВыбора.Добавить(ЭлементСписка.Значение);
КонецЦикла;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ЗаполнитьСписокНовыйНаСервере(ВарКАД)
Список = Новый СписокЗначений;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ВидыВариантовЗначения.Значения КАК Значение,
| ВидыВариантовЗначения.КодЕКАД КАК Код
|ИЗ
| Справочник.ВидыВариантов3CAD.Значения КАК ВидыВариантовЗначения
|ГДЕ
| ВидыВариантовЗначения.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", ВарКАД);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Список.Добавить(Строка(Выборка.Значение) + "\" + Выборка.Код);
КонецЦикла;
Возврат Список;
КонецФункции
Рассмотрим проблему, озвученную в сообщении №6: пользователь выбирает значение, но оно становится видимым только после того, как он переведет фокус на другую ячейку. Проанализируем причину. Это происходит из-за несоответствия типов. Если тип реквизита колонки — СправочникСсылка, а в СписокВыбора вы добавляете Строку, платформа не может сопоставить эти данные автоматически.
Важное правило: тип значения, которое вы добавляете в СписокВыбора, должен строго совпадать с типом реквизита, к которому привязана колонка таблицы. Если колонка ожидает ссылку, добавляйте в список ссылки. Если строку — строки.
Проанализируем более элегантный способ, который позволяет избежать прямого обращения к свойству СписокВыбора элемента. У события НачалоВыбора есть входящий параметр ДанныеВыбора. Если мы заполним его своим списком значений и установим СтандартнаяОбработка = Ложь, платформа сама подставит этот список для выбора в выпадающем меню.
&НаКлиенте
Процедура Таблица1ЗначениеНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
ВарКАД = Элементы.Таблица1.ТекущиеДанные.Вид3CAD;
// Напрямую заполняем ДанныеВыбора
ДанныеВыбора = ПолучитьСписокДляВыбора(ВарКАД);
КонецПроцедуры
Этот метод считается более "чистым", так как он не перегружает свойства элемента управления на форме на постоянной основе, а работает только в контексте одного акта выбора.
Выясним, можно ли решить задачу без написания кода. Если ваши данные связаны на уровне метаданных (например, выбор владельца и подчиненного справочника), лучше использовать встроенный механизм платформы. В свойствах реквизита таблицы найдите пункт Связи параметров выбора. Там можно указать, что выбор в текущем поле должен быть ограничен значением другого поля этой же строки.
Преимущества этого метода:
Проанализируем еще несколько настроек, которые сделают работу пользователя удобнее:
БыстрыйВыбор. В этом случае список будет выпадать сразу при нажатии на поле, без открытия дополнительных окон.НачалоВыбора может замедлить интерфейс. В таких случаях мы рекомендуем один раз прочитать все возможные варианты при открытии формы и кэшировать их в реквизит формы типа Соответствие.Подведем итог: для реализации динамических списков лучше всего подходит событие НачалоВыбора с использованием параметра ДанныеВыбора. При этом крайне важно следить за типизацией данных и не забывать про возможность декларативной настройки через связи параметров выбора, если структура данных это позволяет.